有哪位高手能够提供快速复制数据的方法呢?
情况是这样的 :
 有两个DataSet, 分别为 DataSet1, DataSet2.DataSet1中的某些Field的值, 需要赋到 DataSet2中 ( 或者是需要插入到DataSet2中作为新记录 )但是发现, 无论我采用什么的方法 ( 包括建立数组, 把DataSet1要复制到DataSet2的Field跟 DataSet2的Field 一一对应来直接复制)
赋值语句不论是采用 AsString, Value, AsVariant 还是直接判断类型来赋值当DataSet2的记录数有5000条以上, 就开始不能动了.
刚开始, 每秒钟是处理几乎3000条记录复制的(按20个字段赋值来算)
然后,上4000开始, 复制速度就会降一半
上6000条, 复制速度就更低了( 注意: DataSet1 和DataSet2 的表结构是不一至的 ) 

解决方案 »

  1.   

      m_SorcDataSet.DisableControls;    // 源数据集
      m_SorcDataSet.First;               
      OutDataSet.DisableControls;       // 目标数据集  while not m_SorcDataSet.Eof do    // 记录复制过程
      begin
        OutDataSet.Insert;                               
         CopyRecord;
        OutDataSet.Post;
      end;// 以下是复制过程, FCopyMap[0]的Field数组是指向源DataSet的Field的,  FCopyMap[1]的Field数组是指向目标DataSet的Field的.
    // 定义相当于  : FCopyMap : array [0..1] of array of TField;  procedure CopyRecord;
      var
        i : Integer;
      begin
        for i := Low(FCopyMap[0]) to High(FCopyMap[0]) do
          FCopyMap[1][i].Value := FCopyMap[0][i].Value;
      end;// 这个是测试程序, 我确定没有任何其他 OnValidate事件, Lookup字段等一切会拖慢速度的东西这个东西, 10800条数据, 复制的时候居然要, 第一秒显示速度 3000/s  第二秒就只有 1800/s ,第三秒就 1200/s ,第四秒就900/s 然后一直这样低下去.
    我看不出哪里会有增量循环
      

  2.   

    还有一点很重要的:
    我这个是 DataSet类型 向 TCustomClientSet类型 传数据 ( 表结构不一样, 不用能DataSetProvider )是不是ClientDataSet的索引问题呢? 
    毕竟有索引的时候, 越多数据, 插入就会越慢, 这个是全世界都知道的事情.
    索引是只会有单纯查询的时候才会有效果的, 如果频繁插入记录, 就会越拖越慢
      

  3.   

    用SQL操作,试试每100条或更多进行一次提交另外,有几个疑问之处:
    1、数据库采用什么?
    2、两个数据库不在一台电脑上吧?
    3、Internet应用?
    4、程序采用的三层架构?你的代码看着又不象啊
    5、数据控件用的什么?如何连接数据库?等等,反正看着晕头转向
      

  4.   

    这个复制跟数据库如何连接 ,多少层也没有关系.我只是单纯的从一个已经Open了的DataSet中.
    向另一个DataSet传入记录. 不是向数据库传入记录
      

  5.   

    有没有人注意过这种问题呢 =.= 因最近要搞 内存表, 进行交叉统计和分组显示还有分组统计.
    (也就是实现 SQL 语句中的 Transform ( Access)  和 CUBE (Orcal / SQLServe) 语句做是做出来了, 但是发现分组显示的时候, 从源数据集转移到目标数据集的时候, 发现了这个问题.每秒显示一次复制条数, 瀑布都没下得这么快, 每秒下一半速度! 我倒!
      

  6.   

    楼主,你好,建议将:
    OutDataSet.Insert;
    改为:
    OutDataSet.Append;
      

  7.   

    Append效果一样, 测试过了.依旧是过一秒就慢一倍
      

  8.   

    临时做个view 把需要的数据集成到view中 利用数据库自身的sql 来操作不是更好么
      

  9.   

    采用三层的, 而且还远程HTTP形式, 要求很多东西都必须在前台里面做.而且今天还发一个超级大的问题对ClientDataSet循环做赋值快过头的话.
    就算只有3000条数据进行从一个DataSet 转移到 另一个DataSet. ( 使用 Field1.Value := Field2.Value 的形式 )
    就会弹出 insufficient memory of this operation 这样一个错误出来.
    我晕!
      

  10.   

    第二个DATASET,重新SELECT F1,F2 FROM 一下,看看是不是快很多。注重实效在是最重要的。
      

  11.   

    使用存储过程,或者是SQL命令!
      

  12.   

    DataSet1, DataSet2没有什么显示控件连接着吧?
    比如:DBEdit之类。
      

  13.   

    没有的, 什么连接也没有, 依旧慢得可以.远程数据不是那么容易就老从服务器拿数据的, 能够在前台可以解决,就不能用服务器来解决.
    的确, 写条SQL语句就可以实现分组效果了, 但问题是, 那么多条数据又要从服务拿了.都不知道是啥原因, 而且那个错误还是无法捕捉到的内部消息显示, 然后Abort形式的.最搞笑的就是在循环赋值的时候加个 Sleep(1) 就会正常全部赋值了. 我倒
      

  14.   

    利用数组的问题,涉及类型的转化
    建议你用SQL语句
      

  15.   

    方法一:添加“Application.ProcessMessages;”语句。  procedure CopyRecord; 
      var 
        i : Integer; 
      begin 
        for i := Low(FCopyMap[0]) to High(FCopyMap[0]) do 
        begin
          FCopyMap[1][i].Value := FCopyMap[0][i].Value; 
          Application.ProcessMessages;
        end;
      end; 
    不行的话,就用方法二:写事件赋值1000条就自动COMMIT
    或者
    在数据库端设定COMMIT时间。我感觉是你数据库服务器内存太小……以上仅供参考,不足处,请指出。
      

  16.   

    方法一:添加“Application.ProcessMessages;”语句。  procedure CopyRecord; 
      var 
        i : Integer; 
      begin 
        for i := Low(FCopyMap[0]) to High(FCopyMap[0]) do 
        begin
          FCopyMap[1][i].Value := FCopyMap[0][i].Value; 
          Application.ProcessMessages;
        end;
      end; 
    不行的话,就用方法二:写事件赋值1000条就自动COMMIT
    或者
    在数据库端设定COMMIT时间。我感觉是你数据库服务器内存太小……以上仅供参考,不足处,请指出。
      

  17.   

    加入Application.ProcessMessages; 
    这句的话, 肯定能够复制成功的. 因为影响Application的处理消息足够拖慢速度了.
    我想ClientDataSet之所以出错的原因只有一个: Delta 
    其实利用 ClientDataSet.FieldDefs.Add 创建一个内存表, 有很多时候,是根本不需要去处理Delta
    因为根本不会向服务器提交, 记录修改日志是多余的操作.
    但却没有其他办法, 只有它才有建立内存表的功能不知道TTable能不能这样子创建内存表, 不能够的话或者会采用 Access + TTable形式了.不过结果还是不知道为何 这样复制数据会报错, 而加个Sleep(1) 来拖一下速度就能够正常.今天已经查看过TClientDataSet的代码了, Data 和 Delta 的操作全部是 Ole操作
    而ADO的RecordSet也全部是外面的Com接口. 
    用什么DataSet都不能满足的话.
    自己写个DataSet算了, 实现Field的各种访问就可以了, 虽然麻烦点, 不过也只是写一次
    派分