首页 > 其他分享 >FireDac三种方式批量添加数据的性能对比

FireDac三种方式批量添加数据的性能对比

时间:2023-06-17 23:55:49浏览次数:37  
标签:begin code end SD1 批量 FireDac FDM Form2 添加

我有个程序,需要从CSV中读入数据,对数据进行分析后,然后插入另一个sqlite数据库的数据表。在我的程序中使用了virtual string tree和Firedac,数据大约有13000条,需要转存的数据有11000条左右,转存的字段有8条,除了一条是boolean类型的外都是string类型。

1、直接插入记录

我刚开始采用的方式是对VST的每一条记录进行处理,以前在办公室的机器上,速度虽然有点慢,但还可以接受,大概需要2分多钟,代码如下:

var s:string;  T1:Cardinal;
begin
  s:=InputBox('请输入转存的AIRAC周期号','AIRAC周期','');
  T1:=GetTickCount;
  if s.Trim.IsEmpty  then Exit;
  Form2.g1.MaxValue:=vst1.RootNodeCount;
  Form2.g1.Progress:=0;
  Form2.Label1.Caption:='数据转换需要较长时间,请耐心等候……';
  Form2.Show;
Form2.Update;
  vst1.IterateSubtree(nil,exporttotable,PChar(s)) ;
  
  con2.Close;
  Form2.Close;
  ShowMessage('耗时:'+(GETTICKCOUNT-T1).ToString()+'毫秒');
end;

而VST遍历函数调用的procedure exporttotable 代码如下:

VAR RMKSL:STRING;s:string; I:Integer;
begin
  if Form2.Showing then Form2.g1.Progress:=Form2.g1.Progress+1;
  s:=string(data);
  with pflight(vst1.GetNodeData(node))^ do
  begin
    if (dep_code.Length<>4) or (arr_code.Length<>4) then  Exit;
    RMKSL:='T_DIS='+t_dis+#13#10+
           'MIN_ALT='+min_alt+#13#10+
           rmk;
    SD1.ExecSQL('insert into al_fpl(CODE,dep_apt,arr_apt,fpl,"limit",rmk,airac,is_new) '+
                 'values(:code,:dep,:arr,:fpl,:limit,:rmk,:AR,:isnew)',
                [flt_id,dep_code,arr_code,fpl,limit, RMKSL,s,isnew] );
  end;
end;

在另一台旧电脑上运行,需要大约420多秒,这就有点让人难以接受了。不过好在有进度条显示,不至于造成死机的错觉。

2、使用DML插入数据

后来我换成使用DML插入数据,代码变成了:

var s:string;  T1:Cardinal;
begin
  s:=InputBox('请输入转存的AIRAC周期号','AIRAC周期','');
  T1:=GetTickCount;
  if s.Trim.IsEmpty  then Exit;
  Form2.g1.MaxValue:=vst1.RootNodeCount;
  Form2.g1.Progress:=0;
  Form2.Label1.Caption:='数据转换需要较长时间,请耐心等候……';
  Form2.Show;
  Form2.Update;
  con2.ExecSQL('DELETE FROM AL_FPL WHERE AIRAC=:AR',[s]);
  SD1.SQL.Text:='insert into al_fpl(CODE,dep_apt,arr_apt,fpl,"limit",rmk,airac,is_new) '+
                 'values(:code,:dep,:arr,:fpl,:limit,:rmk,:AR,:isnew)';
  SD1.Params.ArraySize:=vst1.RootNodeCount;
  
  vst1.IterateSubtree(nil,exporttotable,PChar(s)) ;

  SD1.Execute(vst1.RootNodeCount);
  con2.Close;
  Form2.Close;
  ShowMessage('耗时:'+(GETTICKCOUNT-T1).ToString()+'毫秒');
end;

遍历函数的代码是:

VAR RMKSL:STRING;s:string; I:Integer;
begin
  if Form2.Showing then Form2.g1.Progress:=Form2.g1.Progress+1;
  s:=string(data);
  with pflight(vst1.GetNodeData(node))^ do
  begin
    if (dep_code.Length<>4) or (arr_code.Length<>4) then  Exit;
    RMKSL:='T_DIS='+t_dis+#13#10+
           'MIN_ALT='+min_alt+#13#10+
           rmk;
    i:=node.index;
    SD1.Params[0].AsStrings[I]:=flt_id;
    SD1.Params[1].AsStrings[I]:=dep_code;
    SD1.Params[2].AsStrings[I]:=arr_code;
    SD1.Params[3].AsStrings[I]:=fpl;
    SD1.Params[4].AsStrings[I]:=limit;
    SD1.Params[5].AsStrings[I]:=RMKSL;
    SD1.Params[6].AsStrings[I]:=S;
    SD1.Params[7].AsStrings[I]:=flt_id;
  end;
end;

运行结果更慢,大约要460秒,而且最后转换记录部分没有提示条,好像死机了一般。

3、使用FDMEMTABLE和FDLocalSQL

这种方式是先把数据存入到FDMEMTABLE中,然后属地化FDM到同一个库中,最后执行SQL语句insert into table插入数据,代码如下:

var s:string;  T1:Cardinal;
begin
  s:=InputBox('请输入转存的AIRAC周期号','AIRAC周期','');
  T1:=GetTickCount;
  if s.Trim.IsEmpty  then Exit;
  Form2.g1.MaxValue:=vst1.RootNodeCount;
  Form2.g1.Progress:=0;
  with FDM do
  begin
    with FieldDefs.AddFieldDef do
    begin
      Name:='CODE';
      DataType:=ftString;
      Size:=10;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='DEP_APT';
      DataType:=ftString;
      Size:=10;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='ARR_APT';
      DataType:=ftString;
      Size:=10;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='FPL';
      DataType:=ftString;
      Size:=500;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='IS_NEW';
      DataType:=ftBoolean;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='LIMIT';
      DataType:=ftString;
      Size:=500;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='RMK';
      DataType:=ftString;
      Size:=500;
    end;
    with FieldDefs.AddFieldDef do
    begin
      Name:='AIRAC';
      DataType:=ftString;
    end;
    FDM.Open;
  end;
  Form2.Label1.Caption:='数据转换需要较长时间,请耐心等候……';
  Form2.Show;
  Form2.Update;
  con2.ExecSQL('DELETE FROM AL_FPL WHERE AIRAC=:AR',[s]);
  vst1.IterateSubtree(nil,exporttotable,PChar(s)) ;
  FDM.LocalSQL:=FDLocalSQL1;
  SD1.ExecSQL('insert into al_fpl(CODE,dep_apt,arr_apt,fpl,is_new,"limit",rmk,airac) '+
              'SELECT * FROM FDM');
  con2.Close;
  Form2.Close;
  FDM.LocalSQL:=nil;
  fdm.ClearDetails;
  FDM.Close;
  ShowMessage('耗时:'+(GETTICKCOUNT-T1).ToString()+'毫秒');
end;

而遍历函数调用的程序代码如下:

VAR RMKSL:STRING;s:string; I:Integer;
begin
  if Form2.Showing then Form2.g1.Progress:=Form2.g1.Progress+1;
  s:=string(data);
  with pflight(vst1.GetNodeData(node))^ do
  begin
    if (dep_code.Length<>4) or (arr_code.Length<>4) then  Exit;
    RMKSL:='T_DIS='+t_dis+#13#10+
           'MIN_ALT='+min_alt+#13#10+
           rmk;
    I:=node.Index;
    FDM.Append;
    FDM.Fields[0].AsString:=flt_id;
    FDM.Fields[1].AsString:=dep_code;
    FDM.Fields[2].AsString:=arr_code;
    FDM.Fields[3].AsString:=fpl;
    FDM.Fields[4].AsBoolean:=ISNEW;
    FDM.Fields[5].AsString:=LIMIT;
    FDM.Fields[6].AsString:=RMKSL;
    FDM.Fields[7].AsString:=S;
    FDM.Post;
  end;
end;

代码部分长一些,但结果令人满意:

 

短的时候700毫秒,快的时候也不超过1分钟。

标签:begin,code,end,SD1,批量,FireDac,FDM,Form2,添加
From: https://www.cnblogs.com/luohq001/p/17488522.html

相关文章

  • centos添加自定义Systemd服务
    #########################https://zhuanlan.zhihu.com/p/415469149          systemctlenable**nable命令相当于在/etc/systemd/system/目录里添加了一个符号链接,指向/usr/lib/systemd/system/里面的**.service开机时,Systemd会执行/etc/systemd/system......
  • Linux批量文件操作——基于find-xargs
    前言在项目初创阶段,经常会遇到各种文件操作,拷贝头文件,库,批量重命名等。文件结构一复杂,这就将是个无聊的工作。查找文件find可以在目录结构中搜索文件,这是它在man里面的作用描述。那么怎么搜索呢?有多种方式,按文件时间,大小,按文件名,路径名,按文件类型,权限,按用户。而这些方式又可以......
  • 使用 Vue.js 的 CDN(内容分发网络)来添加 Vue.js
    在您的HTML文件中添加script标签,并指定Vue.js的CDN地址。通常可以通过在 <head> 标签或 <body> 标签的底部添加该标签来加载Vue.js。下面是一个常用的Vue.jsCDN地址:<scriptsrc="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>一下是一个小小的案......
  • 批量插入图片(Excel技巧集团)
    以前插入图片以后,图片是在单元格上方的,且同时插入多张图片后,那效果……不忍目睹。但是现在,多出来了个【旋转在单元格中】的功能,图片变成了单元格对象。不止如此,这些图片还可以成为数据验证序列的来源。MM再也不用担心我不会做带照片的花名册了哈哈哈……......
  • 若依框架 前后端分离如何通过菜单管理添加菜单?
    1、创建主目录菜单,如图: 路由地址填写views下的文件名,目录结构参考如下:2、创建子菜单,点击新增 3、填写子菜单信息,参考如下: 路由地址填写:views下的二级文件夹名字组件路径填写为:views下到index.vue的路径(不要写文件后缀),例如:publish/mipsMaterialFiles/index权限字符......
  • 【ElasticSearch】索引(添加)
    【ElasticSearch】索引(添加)RESTAPIPUT/myindex{"settings":{"index":{"number_of_shards":3,"number_of_replicas":3}},"mappings":{"properties":{"......
  • 爬取图片写入时报错--添加个等待时间
    当爬取图片时报requests.exceptions.JSONDecodeError:Invalid\escape:line29column132(char62481)这个错时,在写入的时候加个等待时间就好 ......
  • 批量下载SRR数据
    1.安装prefetch,要安装最新版本2.用conda安装Ascp3.确保都安装好之后执行命令prefetch-Ooutput--option-fileSRR_Acc_List.txt  ......
  • KingbaseES数据库分区表添加主键与索引的建议
    一、初始化测试环境#数据库版本信息KingbaseESV008R006C007B0012onx86_64-pc-linux-gnu,compiledbygcc(GCC)4.1.220080704(RedHat4.1.2-46),64-bit1.创建分区表:createtabletb(idbigint,statdate,nobigint,pdatedate,infovarchar2(50))partitionbyra......
  • Docker容器添加映射端口
    一般在运行容器时,都会通过-p来指定宿主机和容器端口的映射,例如:dockerrun-itd-p本地端口:容器内端口所用镜像名参数说明-d表示后台运行容器-t为docker分配一个伪终端并绑定到容器的标准输入上-i是让容器的标准输入保持打开状态-p指定映射端口即创建容器时,可以设置一个......