FireDAC CopyDataSet 和 CopyRecord 内存丢失有解决方案吗?
Is there a solution to the FireDAC CopyDataSet and CopyRecord memory loss?
我编写了一个将一系列 Paradox table 迁移到 PostgreSQL 数据库的应用程序。不幸的是,当将数据从 Paradox table 导入到 PostgreSQL table 时,内存消耗增加,并且对于较大的 table 之一(100 万条记录),导入崩溃并显示“内存不足”异常。当我使用 CopyDataSet 为整个 table 导入数据时,以及当我使用 CopyRecord 逐条导入数据时,都会发生此崩溃。
我一直在尝试了解此内存泄漏的来源。本来以为是使用FireDAC ODBC驱动的缘故。或者更具体地说,我认为 Microsoft ODBC 驱动程序是源代码。为了对此进行测试,我尝试使用本机 FireDAC Postgres 驱动程序从一个非常大的 PostgreSQL table 导入另一个 PostgreSQL table。但是内存泄漏仍然存在。
我正在使用单向游标 (FetchOptions.Unidirectional := True) 打开源代码 table,文档指出它将丢弃已经在正向扫描中处理过的记录,但泄漏坚持。在所有情况下,我都使用 FDQuery。我尝试使用启用了实时数据 Windows (LDW) 模式的 FDTable,但 Microsoft ODBC 驱动程序与 FDTable 之间存在不兼容,因此这不是一个选项。
这是我用于此测试的基本代码:
FDQuery1.SQL.Text := 'SELECT * FROM sourcetab;';
FDQuery1.FetchOptions.Unidirectional := True;
FDQuery1.FetchOptions.Mode := fmOnDemand;
FDQuery1.Open();
FDQuery2.SQL.Text := 'SELECT * FROM destinationtab WHERE False;';
FDQuery2.Open;
try
while not FDQuery1.Eof do
begin
FDQuery2.Append;
FDQuery2.CopyRecord( FDQuery1 );
FDQuery2.Post;
FDQuery1.Next;
end;
finally
FDQuery1.Close;
FDQuery2.Close;
ShowMessage( 'Done' );
end;
我最后做的是关闭,然后每添加 1000 次就重新打开目标 table。关闭目标 table 会停止内存使用量的线性增长。现在 while 循环看起来像这样:
while not FDQuery1.Eof do
begin
FDQuery2.Append;
FDQuery2.CopyRecord( FDQuery1 );
FDQuery2.Post;
if (FDQuery1.RecNo mod 1000) = 0 then
begin
FDQuery2.Close;
FDQuery2.Open;
end;
FDQuery1.Next;
end;
我尝试了 FDQueries 的许多其他配置,结果都是一样的漏洞。
有没有其他人注意到这种行为,有没有人知道比关闭和重新打开目标查询开销更少的解决方案?
我正在使用任务管理器监视内存使用情况。一旦内存使用量接近 2 GB,程序就会崩溃。正确关闭目标数据集会释放大量内存。
OS:Windows 10 64 位,平台:Delphi Rio 10.3.3,数据库:PostgreSQL 11,目标平台:32 位(无 64 位 Paradox ODBC 驱动程序)
我在使用与您相同的方法时遇到了类似的问题,包括 close/open 解决方法。
内存增加的原因(不是内存泄漏!)是附加到目标查询内部记录缓冲区的记录量。虽然 Unidirectional 有助于限制源查询的内存,但它无法阻止目标查询在记录增加内存后添加记录。由于目标查询只是附加记录,这些记录永远不会被使用或搜索,这完全是浪费。
您可以使用关闭和打开的解决方法,这对我来说也很有效。
作为替代方法,您可以使用简单的 INSERT 查询,不过这需要更多编码才能将源字段放入目标参数中。
编辑: 实际上,查询可以知道如果可以在 Append 和 [=20= 之后释放缓冲区中的所有先前记录]Post 当 Unidirectional 为 True 时,但由于这是一个 FetchOption,因此在 Post.
我编写了一个将一系列 Paradox table 迁移到 PostgreSQL 数据库的应用程序。不幸的是,当将数据从 Paradox table 导入到 PostgreSQL table 时,内存消耗增加,并且对于较大的 table 之一(100 万条记录),导入崩溃并显示“内存不足”异常。当我使用 CopyDataSet 为整个 table 导入数据时,以及当我使用 CopyRecord 逐条导入数据时,都会发生此崩溃。
我一直在尝试了解此内存泄漏的来源。本来以为是使用FireDAC ODBC驱动的缘故。或者更具体地说,我认为 Microsoft ODBC 驱动程序是源代码。为了对此进行测试,我尝试使用本机 FireDAC Postgres 驱动程序从一个非常大的 PostgreSQL table 导入另一个 PostgreSQL table。但是内存泄漏仍然存在。
我正在使用单向游标 (FetchOptions.Unidirectional := True) 打开源代码 table,文档指出它将丢弃已经在正向扫描中处理过的记录,但泄漏坚持。在所有情况下,我都使用 FDQuery。我尝试使用启用了实时数据 Windows (LDW) 模式的 FDTable,但 Microsoft ODBC 驱动程序与 FDTable 之间存在不兼容,因此这不是一个选项。
这是我用于此测试的基本代码:
FDQuery1.SQL.Text := 'SELECT * FROM sourcetab;';
FDQuery1.FetchOptions.Unidirectional := True;
FDQuery1.FetchOptions.Mode := fmOnDemand;
FDQuery1.Open();
FDQuery2.SQL.Text := 'SELECT * FROM destinationtab WHERE False;';
FDQuery2.Open;
try
while not FDQuery1.Eof do
begin
FDQuery2.Append;
FDQuery2.CopyRecord( FDQuery1 );
FDQuery2.Post;
FDQuery1.Next;
end;
finally
FDQuery1.Close;
FDQuery2.Close;
ShowMessage( 'Done' );
end;
我最后做的是关闭,然后每添加 1000 次就重新打开目标 table。关闭目标 table 会停止内存使用量的线性增长。现在 while 循环看起来像这样:
while not FDQuery1.Eof do
begin
FDQuery2.Append;
FDQuery2.CopyRecord( FDQuery1 );
FDQuery2.Post;
if (FDQuery1.RecNo mod 1000) = 0 then
begin
FDQuery2.Close;
FDQuery2.Open;
end;
FDQuery1.Next;
end;
我尝试了 FDQueries 的许多其他配置,结果都是一样的漏洞。
有没有其他人注意到这种行为,有没有人知道比关闭和重新打开目标查询开销更少的解决方案?
我正在使用任务管理器监视内存使用情况。一旦内存使用量接近 2 GB,程序就会崩溃。正确关闭目标数据集会释放大量内存。
OS:Windows 10 64 位,平台:Delphi Rio 10.3.3,数据库:PostgreSQL 11,目标平台:32 位(无 64 位 Paradox ODBC 驱动程序)
我在使用与您相同的方法时遇到了类似的问题,包括 close/open 解决方法。
内存增加的原因(不是内存泄漏!)是附加到目标查询内部记录缓冲区的记录量。虽然 Unidirectional 有助于限制源查询的内存,但它无法阻止目标查询在记录增加内存后添加记录。由于目标查询只是附加记录,这些记录永远不会被使用或搜索,这完全是浪费。
您可以使用关闭和打开的解决方法,这对我来说也很有效。
作为替代方法,您可以使用简单的 INSERT 查询,不过这需要更多编码才能将源字段放入目标参数中。
编辑: 实际上,查询可以知道如果可以在 Append 和 [=20= 之后释放缓冲区中的所有先前记录]Post 当 Unidirectional 为 True 时,但由于这是一个 FetchOption,因此在 Post.