簡體   English   中英

在SQLite,FireDac,Delphi中插入記錄時內存不足

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM