[英]Out of memory when inserting records in SQLite, FireDac, Delphi
我有一個Delphi應用程序,它通過FireDac組件TFDTable將大約200,000條記錄(約1GB)插入到SQLite數據庫中。 插入時,我看到應用程序內存增加,直到出現“ Out of Memory Error”。 我猜想它與緩存和分頁有關,但是我找不到每1000條左右的記錄就可以關閉和重新打開數據庫的解決方案。 思考?
編輯...對不起,這個措辭很薄的問題...代碼很簡單,所以我沒有包含它,但是基本上看起來像這樣:
procedure DoIt;
begin
myDB.Insert;
myDBField1.AsString := StringOfChar('-',1000);
myDB.Post;
end;
現在,我預計內存可能會增加,因為該字符串很可能已復制到數據庫緩存中。 如果我使用GetMemoryManagerState()查看分配,我實際上可以看到這一點。 我希望在某個時刻,當數據寫入磁盤時,緩存中的內存將被刷新。 但是,事實並非如此。 它一直持續到出現“內存不足”錯誤為止。
通常,大多數對象屬性都設置為默認狀態,除了在連接中選擇sqlite並將字段添加到表中。
我知道這里沒有很多事情要做。 但是我也不認為這不會失敗,我希望有人可能也遇到過類似的問題。
TFDTable是一個圍繞查詢對象的精簡包裝,它可以構建用於與基礎DBMS表一起操作的SQL命令。 它具有自己的存儲( Table對象),在其中存儲提取到客戶端的數據以及插入的元組。 但是所有這些都在內存中,沒有底層文件緩存。
盡管可以在插入時清除內部存儲, 但是TFDTable並不是插入如此數量數據的好對象。 更好地使用像TFDQuery這樣的查詢對象, 將其與稱為Array DML的批處理命令執行技術結合使用,甚至可以為本地DBMS引擎帶來真正的性能提升。 而且TFDQuery不會緩存插入的元組。
當您使用索引參數綁定時,FireDAC會為SQLite原生支持此技術,例如,此代碼應插入200次,每批1000個唯一元組:
const
BatchSize = 1000;
TotalSize = 200000;
var
Batch: Integer;
Index: Integer;
begin
FDQuery.SQL.Text := 'INSERT INTO MyTable VALUES (:p1, :p2)';
FDQuery.Params.BindMode := pbByNumber;
FDQuery.Params.ArraySize := BatchSize;
for Batch := 0 to TotalSize div BatchSize - 1 do
begin
for Index := 0 to BatchSize - 1 do
begin
FDQuery.Params[0].AsIntegers[Index] := (Batch * BatchSize) + Index;
FDQuery.Params[1].AsWideStrings[Index] := 'Some Unicode string value';
end;
FDQuery.Execute(BatchSize, 0);
end;
end;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.