【问题标题】:How to improve data insert/update performance?如何提高数据插入/更新性能?
【发布时间】:2012-09-13 03:02:40
【问题描述】:

我需要提高数据加载的性能。当前算法从表中进行全选:

select Field1, Field2,...,FieldN from Table1 order by FieldM

从文本文件中读取新数据(例如,每个数据表行的文本文件行)。 该表有一个主键,包含两个字段。对于文本文件的每一行,它通过这两个字段(即主键)定位必要的行。

query.Locate('Field1;Field2',VarArrayOf([Value1,Value2]),[]);

如果Locate 返回True,则编辑该行,否则添加一个新行。

因此,就表包含大约 200000 行而言,每个Locate 操作都需要一定的时间……因此它每秒可以更新大约 5-6 行。

我应该考虑哪些事情来改进它?

可能用单独的查询替换通过这个很棒的选择进行的定位?

【问题讨论】:

    标签: sql-server performance delphi delphi-7 ado


    【解决方案1】:

    不要使用 Locate()。如果您使用 locate() 那么 Delphi 在客户端搜索行只是从您的查询中扫描行集,这需要很多时间。

    如果您有权访问 MSSQL 来创建存储过程,则创建以下过程并在没有任何条件的情况下为您的 TEXT 文件中的每一行运行它(在 Delphi 中使用 TAdoStoredProc.ExecProc)。所以在这种情况下,您不需要先选择和定位程序。如果找到 Filed1 和 Field2,它会更新记录,如果没有,则插入。

    CREATE PROCEDURE dbo.update_table1 
    @Field1 int, --key1
    @Field2 int, --key2
    @Field3 int, -- data fileds
    @Field4 int
    
    AS
    
    SET NOCOUNT ON
    update table1 set Field3=@Field3,Field4=@Field4 
            where Field1=@Field1 and Field2=@Field2;
    IF(@@Rowcount=0)
    BEGIN
         insert into table1(Field1,Field2,Field3,Field4) 
                    values (@Field1,@Field2,@Field3,@Field4);
    END
    GO
    

    这是使用 ADO 调用此存储过程的 Delphi 代码:

    ......
    var 
         ADOStoredP: TADOStoredProc;
    
      ......
    begin
    
    ........
        ADOStoredP:=TADOStoredProc.Create(nil);
       try
          ADOStoredP.Connection:=DataMod.SQL_ADOConnection; //Your ADO Connection instance here
          ADOStoredP.ProcedureName:='Update_table1';
          ADOStoredP.Parameters.CreateParameter('@Field1', ftInteger, pdInput, 0, 0);
          ADOStoredP.Parameters.CreateParameter('@Field2', ftInteger, pdInput, 0, 0);
          ADOStoredP.Parameters.CreateParameter('@Field3', ftInteger, pdInput, 0, 0);
          ADOStoredP.Parameters.CreateParameter('@Field4', ftInteger, pdInput, 0, 0);
    
          While () -- Your text file loop here
          begin
    
          ADOStoredP.Parameters.ParamByName('@Field1').Value:=Field1 value from text file here;
          ADOStoredP.Parameters.ParamByName('@Field2').Value:=Field2 value from text file here;
          ADOStoredP.Parameters.ParamByName('@Field3').Value:=Field3 value from text file here;
          ADOStoredP.Parameters.ParamByName('@Field4').Value:=Field4 value from text file here;
    
          ADOStoredP.ExecProc;
    
          end
    
        finally
          if Assigned(ADOStoredP) then
            begin
             ADOStoredP.Free;
            end;
        end;
    
    ........
    end;
    

    【讨论】:

    • 此解决方案将加载时间从 4 小时减少到不到 4 分钟。我真的很感谢你的帮助!谢谢!
    【解决方案2】:
    1. 如果可能,您应该将文本文件发送到运行 SQL Server 的服务器。然后使用OPENROWSET(BULK) 打开文本文件(请参阅“E. 使用带有格式文件的 OPENROWSET BULK 提供程序从文本文件中检索行”)。
    2. 如果无法将文本文件发送到服务器,则创建临时或持久数据库表并使用 INSERT 将所有文本文件行插入表中。
    3. 如果您使用的是 SQL Server 2008,那么您应该使用 MERGE 运算符。如果 SQL Server 版本比较旧,那么可以使用两个 SQL 命令:UPDATE 和 INSERT。并作为数据源使用 (1) OPENROWSET 或 (2) DB 表。

    【讨论】:

    • 虽然将 valex 的答案应用于我的情况要容易得多,但感谢您的帮助。目标 sql server 甚至是 2000。一个相当老的。由于 valex 给出的想法,重新制作整个算法以将文件加载到某个临时表中(等等..)与我所取得的成就(以及我为此花费的时间)相比,不值得任何性能提升(如果有的话) .无论如何,谢谢!
    猜你喜欢
    • 2016-12-25
    • 2021-08-31
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多