下面是我的代码:
procedure TForm1.Button1Click(Sender: TObject);
var
nodes:TTreenode;
a,b:tdatetime;
begin
a:=now;
begin
with ADOQuery1 do
begin
close;
sql.clear;
sql.add('select id,caption from lianxi where fjid=''0'' and lb=''father'' order by id');
open;
while not eof do
begin
nodes:=TTreenode.create(nil);
nodes:=Treeview1.Items.add(nil,FieldbyName('caption').AsString);
Add(nodes,ADOQuery1.fieldbyname('id').asstring);
next;
end;
end;
end;
b:=now;
ShowMessage(IntToStr(SecondsBetween(A,B)));
end;procedure TForm1.Add(var Nodes:TTreeNode;x:string);
var
  sub:TTreenode;
  List:TADOQuery;
begin
    List:=TAdoQuery.Create(nil);
    List.Connection:=ADOConnection1;
  with List do
  begin
    Close;
    Sql.Clear;
    Sql.Add('select id,caption from lianxi where fjid=:par order by id');
    parameters.ParamByName('par').Value:=x;
    open;
    While not Eof do
    begin
      sub:=Treeview1.Items.AddChild(nodes,FieldbyName('caption').AsString);
      add(sub,fieldbyname('id').asstring);
      next;
    end;
  end;
    List.Free;
end;
32000条数据要90秒,在id列唯一索引,fjid聚集索引,id,fjid,caption组合索引
请问如何提高我这个算法的效率?

解决方案 »

  1.   

    用一个全局的记录集,
    然后在递归的时候直接在记录集上使用filter来得出子节点并增加
    这样就不用每次递归都去连接数据库
      

  2.   

    while not eof do 
    begin 
    nodes:=TTreenode.create(nil); 
    nodes:=Treeview1.Items.add(nil,FieldbyName('caption').AsString); 
    Add(nodes,ADOQuery1.fieldbyname('id').asstring); //这个函数在循环里面
    next; 
    end; 
    end; 
    end; 
    b:=now; 
    ShowMessage(IntToStr(SecondsBetween(A,B))); 
    end; procedure TForm1.Add(var Nodes:TTreeNode;x:string); 
    var 
      sub:TTreenode; 
      List:TADOQuery; 
    begin 
        List:=TAdoQuery.Create(nil); //因为在循里面使用本函数,每次都创建,最后释放,是不是花了不少时间    List.Connection:=ADOConnection1; 
      with List do 
      begin 
        Close; 
        Sql.Clear; 
        Sql.Add('select id,caption from lianxi where fjid=:par order by id'); 
        parameters.ParamByName('par').Value:=x; 
        open; 
        While not Eof do 
        begin 
          sub:=Treeview1.Items.AddChild(nodes,FieldbyName('caption').AsString); 
          add(sub,fieldbyname('id').asstring); //这儿又在递归调用,又在循环,能不浪费时间吗,个人认为,循环和递归应选择其一,不应把两者放在一起使用      next; 
        end; 
      end; 
        List.Free; 
    end; 
      

  3.   

    前一段时间正好整理了一个,供参考
    递归加载树形列表的过程
    http://blog.csdn.net/tjianliang/archive/2008/08/28/2844848.aspx
    数据一次性从数据库取出,然后采用递归加载。
    如果还是很慢,应考虑分次读取和加载
      

  4.   

     List:=TAdoQuery.Create(nil); 
     tadoquery,应该用控件,临时创建是要时间的。用控件是静态调用的。速度快很多,
     另外,就是不一次性取所有数据。等用户点X的时候,再去展开数据。因为没人会看
    所有数据。不要太强调技术,没有实际意义的技术,是没有用的。
      

  5.   

    看了上面的回复,但每天干了一天代码,没耐心看代码。这方面我倒是也接触过,说说自己的看法。
    1. 有人说TAdoQuery不要临时创建,如果使用递归的话,必须重新创建,必要误导。
    2. 如果数据量很大,可以采用一次只装入一层,或几层的方式来进行。写个record放入Node的data中,record中有个布尔类型标识有否装入下级。如果没装,在点击时,先装入,再展开,并设置布尔值为已装入即可。 
       以前有个项目是进行电厂设备管理的,有很多万条设备,每个设备有几十个字段,一次太吃力,只能采用这种方式,而且响应时间都是可以接收的,每次检索也就几十条最多几百条数据,非常快。3.数据量不大的递归,数据量大的,建议还是需要时装入,速度还是挺快的。毕竟用户不是吃饱了每个节点都去点一下