Я написал приложение, которое переносит серию таблиц Paradox в базу данных PostgreSQL. К сожалению, при импорте данных из таблицы Paradox в таблицу PostgreSQL увеличивается потребление памяти, а для одной из более крупных таблиц (1 миллион записей) происходит сбой импорта с исключением «недостаточно памяти». Этот cra sh возникает как при импорте данных с использованием CopyDataSet для таблицы в целом, так и при использовании CopyRecord для импорта данных по записи.
Я экспериментировал с узнать источник этой утечки памяти. Первоначально я думал, что источником является драйвер FireDA C ODB C. Или, точнее, я думал, что источником является драйвер Microsoft ODB C. Чтобы проверить это, я попытался импортировать из очень большой таблицы PostgreSQL в другую таблицу PostgreSQL, используя собственный драйвер FireDA C Postgres. Но утечка памяти сохранилась.
Я открываю исходную таблицу с помощью однонаправленного курсора (FetchOptions.Unidirectional: = True), который в состояниях документации будет отбрасывать записи, которые уже были обработаны при прямом сканировании, но утечка сохранилась. Во всех случаях я использовал FDQuery. Я пытался использовать FDTable с включенным режимом Live Data Windows (LDW), но существует несовместимость между драйвером Microsoft ODB C и FDTable, поэтому это было невозможно.
Здесь это базовый c код, который я использую для этого теста:
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;
Я закончил тем, что закрыл и повторно открывал таблицу назначения каждые 1 000 добавлений. Закрытие таблицы назначения останавливает линейное увеличение использования памяти. Теперь, когда l oop выглядит следующим образом:
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 ГБ, происходит сбой программы. Правильное закрытие набора данных назначения освобождает большой объем памяти.
ОС: Windows 10 64-разрядная, платформа: Delphi Rio 10.3.3, база данных: PostgreSQL 11, целевая платформа: 32- бит (без 64-битного драйвера Paradox ODB C)