不知道微软还有没有脸,用VB的ADO后期绑定测试了一下相同的流程,竟然要一个多小时! 如何提高ADO简单过程(Edit…Post Next)的效率(500分)

  • 主题发起人 主题发起人 jsxjd
  • 开始时间 开始时间
to jsxjd
>>>>这样的库结构对构造树是非常有利的,一次扫描就可以了。PIII550近一万条记录不到9秒。
粗率看一下你下面的代码发现可以优化一下,不知道对不对

你增加节点的时候,找父节点不需要从第一个节点开始向后找,
你可以把上一个增加的节点保存到一个临时变量中,看它是不是当前要增加节点的父节点,
若不是,在看它的父节点能不能做当前要当前要增加节点的父节点,若不是在继续....
直到找到或者已经到顶了,写一个递归就可以了,查找父节点的函数如下:
function Tfrm_zzqk.[red]SearchParentNode[/red](StartNode: TTreeNode;
bh: string): TTreeNode;
begin
Result := nil;
if Assigned(StartNode) then
begin
if Copy(bh, 1, length(PNodeData(StartNode.Data)^.bh)) = PNodeData(StartNode.Data)^.bh then
Result := StartNode
else
Result := [red]SearchParentNode[/red](StartNode.Parent, bh);
end;
end;
 
查找父节点是可以做成递归,因为知道 bh ,它的父节点的 bh 是确定的,
如果没有父节点,找父节点的父节点。等等。

我理解你的意思,对了,代码后面补0可能要变一下。
Result := SearchParentNode(StartNode.Parent, perentCode(bh));
/////////////////
但是用递归,应该不会提高效率的!!!
 
用递归会降低效率的主要理由可能是搜索树。

还有,树中最多的节点一般是最低层的节点,
用SearchParentNode(StartNode.Parent, perentCode(bh));时
肯定要把上一个节点作为 StartNode
这样 SearchParentNode 一次成功率会比较低。

 
对,后面的判断是否是父节点的表达式对你的字段后面有0的是不能用
>>>Result:=SearchParentNode(StartNode.Parent, bh);//就是看为当前要增加的节点找父节点,就必须用自己的编号去找
还有找父节点用
 
SearchParentNode最多执行的次数是已经建的树的Level,
 
忘了讲了,数据接是按编号排过序的,这样递归找父节点效率一般比较高
 
按你上面的做可以优化代码,但不一定能优化效率。

但你的这种情况对无最多层次限制的树是非常合适的。

不知道我这么说行不行??
 
对,刚才详细看了一下,你的代码的确在建固定层数的树效率是比我的的高,
毕竟你把每一个层数的最后节点都保存了,不用再找了
[red]不过强烈建议不要用Delphi的TreeView,用VB的可以比Delphi的能快5倍以上,[/red]
 
好主意,但那个东东依赖 activeX,存在安装问题。

我以前的一个程序用的就是 VB 的TreeView
而且安装低版本 OFiice 以后,如果再卸掉,我的程序就不正常。
再怎么搞也不行,最后只有重做系统。
 
>>>你上面的TREE,好象是关于TREE存盘的
既然你树的层数是固定的,那你可以在表中加个Level字段,
这样你可以通过SQL语句来达到通过树来修改节点ID的效果

你认为可以吗???????
 
>>>>>而且安装低版本 OFiice 以后,如果再卸掉,我的程序就不正常。
你做安装盘的时候不要把MSCOMCTL.OCX文件放在系统目录,
就不怕覆盖和版本兼容的问题了(我都是怎么做的)
 
我这里的情况是:
11000000
11110000
11111100
11111111
如果都是这样就好办了。但会有以下的情况
11000000
11111111 这样 11111111 的父节点是 11000000 而不是 11111100

用SQL的标准函数,不通过搜索无法确定一个代码的父节点代码。
 
就你这中情况也可以写,我以前见过
 
SQL也能写出来,但我担心效率,不过可以试试。
 
没有仔细的看帖子,凭自己的想象写一点。[:)]
首先使用
while not eof
begin
edit
post
next
end;这种方式慢,这是很正常的,同时你使用caption显示也浪费了一定速度(当然不是主要原因)
使用SQL来进行更新当然快了,全部操作基本都在“后台”完成了(即使是本地数据库,也可以理解为由数据库驱动程序自己完成的)

你的问题有一个笨方法,使用TStringList、SQL写入来完成,放心SQL速度一般会比使用ADO那样edit快许多。
 
首先谢谢答复!
我现在的问题可以这么说:
如果确实有这样的表,前后记录的值存在一定的关联。
一定要执行这样的澈程,是否有通过环境设置来优化的可能。
另外 TStringList 是一办法,但它的最大行数毕竟有限制。
而且资源消耗无法容忍。
当然一万条是不成问题的。如果更多呢?
 
这跟ADO没关系,类似tquery方式就是这么慢,不信你换其他数据库接口试试看.
 
我已经试过用VB的ADO后期绑定,这不是 TQuery TTable 的问题!

另外,ADO应该是不太完善的。
用ADO如何物理删除 VF DBF 表的记录?????????
 
本以为可以用以下SQL测试一下以上功能的效率:
update gypcbz set p_id=iif(right(cpdm,6)="000000","",(select top 1 cpdm from gypcbz a where (a.cpdm=left(gypcbz.cpdm,6)+"00" or a.cpdm=left(gypcbz.cpdm,4)+"0000" or a.cpdm=left(gypcbz.cpdm,3)+"00000" or a.cpdm=left(gypcbz.cpdm,2)+"000000") and a.cpdm<gypcbz.cpdm order by a.cpdm desc))


可VFP根本不支持“单值型”子查询:
update gypcbz set p_id=(select top 1 cpdm from xx)
 
对不起各位, 没仔细看代码。我有几点疑问:
1、上述代码到底是在构造树还是在保存树?
2、我没理解错的话, cpdm中保存的应当是子节点及所有父节点的代码吧? 我的疑问是, 为什么这个字段要做成定长的? 即父节点编码为什么不能是'11'而必须是'11000000'呢? 如果是不定长的, 根本不需要分析字符串, 简单判断长度即可知道该节点属于那一层了。
3、凭直觉我觉得while .. do ... end中间包含的两个for不是必须的。
4、单从ado的效率上来说, 我觉得遍历一遍生成所有的sql语句。 然后一次性提交这一批sql语句效率至少比edit; post; next提高50%。 只是我不知道对vfp库是否支持多条sql语句一起执行, 或者一次提交的sql语句长度是否有什么限制? (sql server下我试过3.5M的sql语句一次提交)
 
后退
顶部