继上个帖子的问题,继续研究下,希望大神能解答
https://bbs.csdn.net/topics/392406195对比了一下ListView 和 DBGrid直接写入数据速度(3000条数据,每条数据60个字段)
DBGrid:  Append,FieldByName 写入用时2秒多
ListView:SubItems.Add 写入用时4秒多
光这么看貌似DBGrid略胜一筹
但是,ListView有一个OwnerData属性,开启后使用OnData方法刷新数据的时间只有0.02秒所以问题来了,DBGrid是否也有ListView这种机制,不在屏幕中的数据不刷出来,向下滚动的时候才刷出来
如果有的话要如何实现,最好能贴一下简易的代码,当然了别用类似Page Down这种按一下下一页这种方式,需要和ListView一样一个页面显示,滚动条下来自然的刷出来

解决方案 »

  1.   

    可能有人会说,既然ListView控件刷新效率这么高,我还干嘛闲着蛋疼想把ListView换成DBGrid
    而且控件一换,这个界面中于此控件相关代码全部都要重写,费时费劲
    主要原因有2个,
    1,,DBGrid控件可以给字段增加数据类型ListView不行,而实际运用中需要更具数据类型来决定左对齐右对齐,或者别的效果,ListView只能每一个字段手动来调整,太麻烦,目前已经有60多个字段了,保不齐后面随着需求的增加字段持续变多,维护起来太累
    2,排序。现在在OnData刷新数据之前,先要对一个Tlist数据用Sort进行一次排序,极大的耗费时间,高峰时界面可能直接卡死(此界面数据实时性要求非常高,如果监控3000个客户,实时主推刷新,峰值可能每秒成百上千次刷新频率),而DBGrid是通过添加索引字段来排序,效率要快很多。
      

  2.   

    是不是我这情况可以 ClientDataSet 设置 packetRecords?
    但是我packetRecords输入了一个条目数,还是没啥用,不知道要怎么使用
      

  3.   

    FetchOnDemand 设置成True了,packetRecords 设置了50,但还是全刷
      

  4.   

    上次的帖子不是已经解决了DBGrid的性能问题了吗?当时是3000行3列的数据,只用了0.012秒,今天我测试了一下,就算是60列,也只用了0.25秒,难道你的电脑或网络很慢?
      

  5.   

    如果你用的带Firedac的Delphi,用TFDMemTable代替TClientDataSet, 60列3000行数据只需0.12秒就完成了
      

  6.   


    之前主要是没有测试多字段情况,两三个字段是很快,但是这次测试了60个字段一下就卡起来了,莫非是我代码没写好,还有就是目前我用delphi6 没有TFDMemTableprocedure TForm1.Button1Click(Sender: TObject);
    var
      BeginTime: TDateTime;
      iLoop,jLoop: Integer;
    begin
      BeginTime := Now;
      with ClientDataSet1 do
      begin
        DisableControls;     //切断 ClientDataSet 和控件的关联
        for iLoop := 0 to 3000 do
        begin
          Append;
          for jLoop := 1 to 60 do
          begin
            FieldByName('Field'+IntToStr(jLoop)).AsString := 'Code' + intToStr(iLoop);
          end;
        end;
        Post;
        First;
        EnableControls;      //恢复 ClientDataSet 和控件的关联
      end;
      Edit1.Text := FormatDateTime('hh:nn:ss.zzz', Now-BeginTime);  BeginTime := Now;
      ListView1.Items.Count := 3000;
      Edit3.Text := FormatDateTime('hh:nn:ss.zzz', Now-BeginTime);
    end;
      

  7.   


    另外还是想问一下,DBGrid有木有类似于ListView中OnData的实现方式,毕竟几遍你这边测试的 60列,0.25秒和OnData0.02 也有着十几倍速度的差距
      

  8.   

    可能是Delphi版本太老了, 不能用新版本?
      

  9.   


    版本的确没办法升级,毕竟公司大家统一的开发环境,不是随便就能换的
    TFDMemTable不能使用其实问题也不是很大了,0.25秒种方式其实也能接受
    但不知道代码要怎么实现,麻烦大神提供下代码来看看,我的代码上买贴出来了,就是要2秒左右
      

  10.   

    type
      TForm1 = class(TForm)
        Button1: TButton;
        DataSource1: TDataSource;
        Edit1: TEdit;
        耗时: TLabel;
        DBGrid1: TDBGridEh;
        ClientDataSet1: TClientDataSet;
        procedure Button1Click(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private  public
        { Public declarations }
      end;var
      Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
    var
      I: Integer;
      S: String;
    begin
      with ClientDataSet1.FieldDefs do
      begin
        for I := 1 to 20 do
        begin
          S := IntToStr(I);
          Add('Code'  + S, ftString, 8 );
          Add('Name'  + S, ftString, 20);
          Add('Number'+ S, ftInteger   );
        end;
      end;
      DataSource1.DataSet := ClientDataSet1;
      DBGrid1.DataSource := DataSource1;
    end;procedure TForm1.Button1Click(Sender: TObject);
    var
      BeginTime: TDateTime;
      I, J: Integer;
      S: String;
    begin
      BeginTime := Now;
      with ClientDataSet1 do
      begin
        DisableControls;
        Close;
        CreateDataSet;
        Open;
        LogChanges := False;
        for I := 1 to 3000 do
        begin
          Append;
          for J := 1 to 20 do
          begin
            S := IntToStr(J);
            FieldByName('Code'+ S).AsString := 'Code' + intToStr(I);
            FieldByName('Name'+ S).AsString := 'Name' + intToStr(I);
            FieldByName('Number'+ S).AsInteger := I;
          end;
          Post;
        end;
        EnableControls;
      end;
      Edit1.Text := FormatDateTime('hh:nn:ss.zzz', Now-BeginTime);
    end;
      

  11.   

    你好像少了下面几句:
        Close;
        CreateDataSet;
        Open;
        LogChanges := False;另外,post放的位置也不对
      

  12.   


    我是界面初始化的时候已经做了CreateDataSet
    点击按钮只是插入数据,所以就没有那几句
    然后post放在外面感觉可以少提交几次,理论应该还会快一点
      

  13.   

    测试了一下和这些代码没啥关系,把你代码完完全全复制黏贴过来,还是2秒,见鬼了
    机器性能应该不至于,去年的苹果电脑装虚拟机的,内存分配了8个G,硬盘是固态的,跑跑这种简单程序应该不会有性能问题才对
    严重怀疑是delphi版本问题
      

  14.   

    估计是虚拟机的缘故了,你把程序方式copy到非虚拟机上运行一下就知道是不是了。
      

  15.   

    那你自己找一台电脑,装一下新版本的delphi(例如Delphi 11.2),试试编译运行一下, 看看是不是版本的问题。
      

  16.   

    如果单纯是显示和刷新问题,select top n * from TABLE也可以解决,就是太麻烦了
      

  17.   


    我们不是直接访问数据库的,前台用功能号的形式访问后台so,so访问数据库,打包好数据返回给前台所以DBGrid控件也只能手动插入数据Append,FieldByName,Post 这样操作
      

  18.   

    感觉上使用DBGrid比较好,它能与数据集相关联,而ListView功能 上不及DBGrid。
      

  19.   

    安装EhLib,用其中的TMemTableEh代替delphi自带的TClientDataSet试试
      

  20.   

    DBGrid的数据显示方式,跟ListView的自画方式(OwnerDraw)是类似的。因为DBGrid只是展示它下面关联的数据集的数据,而数据本身就已经存在了,不像ListView普通情况下要执行AddItems的操作形成展示数据,所以DBGrid的在展示数据上速度更快。而如果采用ListView的OwnerDraw,其欲展示的数据,普通做法是预先生成在内存中,在展示数据时也只是展示可见部分,不可见的行列不会去读取和处理的,所以速度也会很快。