我们从UniDAC 4.1迁移到5.0(简单地重建或使用新版本的应用程序),并在我们的数据泵例程中发现了巨大的退化。
运行pgfouine捕获许多查询,如:
SELECT current_database() AS DATATYPE_CATALOG,
n.nspname AS DATATYPE_SCHEMA,
t.typname AS DATATYPE_NAME,
t.oid AS DATATYPE_OID,
t.typlen AS DATATYPE_LENGTH,
CASE WHEN t.typtype = 'b' THEN 'base'
WHEN t.typtype = 'c' THEN 'composite'
WHEN t.typtype = 'd' THEN 'domain'
WHEN t.typtype = 'e' THEN 'enum'
WHEN t.typtype = 'p' THEN 'pseudo'
END::varchar(9) AS DATATYPE_TYPE,
t.typrelid AS TABLE_OID,
t.typbasetype AS DATATYPE_BASETYPE
FROM pg_type t
INNER JOIN pg_namespace n ON n.oid = t.typnamespace
WHERE t.oid = '' AND t.typtype = ''
ORDER BY n.nspname, t.typname;
对于210,000个数据插入执行超过1,100,000次。为什么会发生这种情况,如何在当前版本中避免这种情况?
我们做TUniQuery。在插入循环之前准备一次,并在其中重新分配查询参数。在UniDAC 4.1上,它工作得很好。
乌利希期刊指南。搜索最小可复制的应用程序/数据库,我发现,如果发生我们在表中使用域数据类型
CREATE DOMAIN id_dom AS integer NOT NULL;
CREATE TABLE test_table (id id_dom);
最小的应用程序:
program minProject;
{$APPTYPE CONSOLE}
uses
Messages, SysUtils, Variants,
DB, DBAccess, Uni, UniProvider, PostgreSQLUniProvider;
const text = 'insert into test_table (id) values (:id)';
var
qu:TUniQuery;
PostgreSQL: TPostgreSQLUniProvider;
UniConnection1: TUniConnection;
i: Integer;
ids: Variant;
begin
{ TODO -oUser -cConsole Main : Insert code here }
UniConnection1 := TUniConnection.Create(nil);
PostgreSQL := TPostgreSQLUniProvider.Create(UniConnection1);
UniConnection1.ProviderName := 'PostgreSQL';
UniConnection1.Username := '';
UniConnection1.Password := '';
UniConnection1.Server := '';
UniConnection1.Database := 'test';
UniConnection1.SpecificOptions.Values['ProtocolVersion'] := 'pv30';
ids := VarArrayOf([41750, 41751, 41752]);
qu := TUniQuery.Create(UniConnection1);
qu.Connection := UniConnection1;
qu.SQL.Text := text;
qu.Prepare;
for I := 0 to 2 do
begin
qu.ParamByName('id').AsInteger := ids[i];
qu.Execute;
end;
qu.Close();
end.
如果使用通常的数据类型,则所有都可以。
UPD2:
DevArt的回复:
谢谢你提供的信息。我们已经重现了这个问题,正在进行调查。我们一有结果就会通知你。
在5.0.1版本中添加了对域类型的完全支持(在4.1版本中没有),因此我们必须从数据库请求额外的元数据。我们已经发布了新版本的UniDAC 5.0.2,它包含了一个修复,可以提高处理域类型时的性能。现在UniDAC的工作速度与UniDAC 4.6.12一样快,即使查询包含域数据类型的字段。