DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: deliping
今日帖子: 2
在线用户: 3
导航: 论坛 -> 数据库专区 斑竹:liumazi,waterstone  
作者:
男 ww1000 (Delphis) ▲▲▲▲▲ -
普通会员
2024/3/2 13:26:40
标题:
请教一下,关于FireDac+Sqlite+DML写入数据后,数据库文件很大的问题 浏览:345
加入我的收藏
楼主: 操作:使用下面代码写入 200w 条记录(分20次,因内存抵不住)
问题:生成的数据库Db文件很大,而且DB文件大小,时大时小,有时700M(偶尔),有时1100M(大部分时间),但数据查到是一样的;
请教:我想数据库文件比较小,如700M以下,不知道哪里可以优化一下;
请问这种一次性写入 100~2000w 数据写入 Db,有没有什么好建议可以提供?

谢谢...

1:D11/12:FireDac+Sqlite 代码建库
       FCon1:= TFDConnection.Create(Nil);  
          with FCon1 do
          begin
          Connected := False;          
          Params.Values['DriverID']     := 'SQLite';
          Params.Values['Database']     := 'D:\123.db'; 
          Params.Values['OpenMode']     := 'CreateUTF8';
          Params.Values['StringFormat'] := 'Unicode';
          Connected := True;
          end;

        FCon1.ExecSQL('CREATE TABLE ABC(AA TEXT, BB INT64)'); //没有索引,没有自动ID

          FQ1:= TFDQuery.Create(nil);
          with FQ1 do
          begin
          Close;
          Connection := FCon1;
          IndexesActive:=False;
          AutoCalcFields:=False;
          CachedUpdates:=True;
          FetchOptions.Mode := fmManual; 
          FetchOptions.AutoFetchAll:= afDisable;      
          FetchOptions.RecordCountMode := cmVisible;  
          FetchOptions.CursorKind := ckForwardOnly;   
          FetchOptions.Unidirectional:=True;          
          FetchOptions.AutoClose := False;
          ResourceOptions.SilentMode := True;       
          end;


2:循环 i 次,使用 DML 批量写入:

T1:0~512长度的字符串 ,各国文字串
F1:0~100亿的数字长度 

   For i := 0 to 20-1 do    // i = 0~200 
     begin
       FCon1.StartTransaction;

          FQ1.DisableControls;  
          FQ1.SQL.Text :='insert into ABC(AA TEXT, BB INT64) values (:s1, :s2)';
          FQ1.Params.BindMode := pbByNumber;
          FQ1.Params.ArraySize := 100000;   //10w~20w

          for j :=0 to (100000-1) do    //这里会动态套入不重复
          begin
          FQ1.Params[0].AsStrings[j] := T1;
          FQ1.Params[1].AsLargeInts[j] := F1;
          end;

          FQ1.Execute(100000, 0);

       FCon1.Commit;  //要每次都提交数据库,否则内存不足
       FCon1.Close;   //不知道哪里设置问题,必须Close才会写入DB,否则只会留在内存,直至溢出内存
    end;
----------------------------------------------
阳光总在
作者:
男 hncsl (hncsl) ★☆☆☆☆ -
普通会员
2024/3/3 9:06:18
1楼:  if not FDConnection1.Connected then
    FDConnection1.Connected := True;

  sTxt := 'insert into ABC(AA, BB) values (:s1, :s2)';
  FDConnection1.StartTransaction;
  try
    for i := 0 to 100000 do // 这里会动态套入不重复     (100000-1)
    begin
      F1 := Randomrange(0, 65535);
      T1 := 'sssss';
      FDQuery1.SQL.Text := sTxt;
      FDQuery1.ParamByName('s1').DataType := ftString;
      FDQuery1.ParamByName('s2').DataType := ftInteger;
      FDQuery1.Prepare;
      FDQuery1.ParamByName('s1').AsString := T1;
      FDQuery1.ParamByName('s2').AsInteger := F1;
      FDQuery1.ExecSQL;
    end;
    FDConnection1.Commit;

    ShowMessage('Inserted ' + i.ToString + ' Records!') ;
  except
    on E: Exception do
    begin
      FDConnection1.Rollback;
      ShowMessage(E.Message);
    end;

  end;
这个测试未关闭FDConnection1时,可以直接写入;如大批量插入,还是使用批量插入的SQL语句。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2024/3/3 11:15:03
2楼: 楼主说:

//不知道哪里设置问题,必须Close才会写入DB,否则只会留在内存,直至溢出内存

----------
你是不是设置了 CatchedUpdate 为 True?
----------------------------------------------
-
作者:
男 yookee (yookee) ★☆☆☆☆ -
盒子活跃会员
2024/3/3 11:26:31
2楼: FireDac+Sqlite+DML的上限不应该这么低
我曾经用过
FQ1.Params.ArraySize := N1; // N1>5e7,为了应对偶尔碰到的数据风暴
实际
FQ1.Execute(N2, 0); // N2>5e5

你是用64bit编译的吗,我做上述操作时程序占用内存峰值过8G了,生成的数据库文件500M左右。你的T1较长时,我估计机子配32G的内存肯定够用的。

如果你是反复删除插入数据,在意数据库大小的话,每次重新大量插入前用VACUUM清理一下
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行66.40625毫秒 RSS