数据集比较的效率问题(超超级难题)

liangyong007a 2007-08-09 09:52:32
AdoDataSet1和AdoDataSet2两个数据集结构一样,主键为字段Ryid,每个库均有2000个以上记录,现要求一个最高效率的算法:比较两个数据集中的记录,如果AdoDataSet1中的记录AdoDataSet2中没有,则把这条记录添加至AdoDataSet2中。 因为数据集来源有些字段不是来自表,不能用SQL语句来比较记录来合并不同值。
我用传统的算法:
var
ls_ryid:string;
i:Integer;
begin
AdoDataSet1.First;
AdoDataSet2.First;
while Not AdoDataSet1.Eof do
begin
ls_ryid:=AdoDataSet1.FieldbyName('Ryid').AsString;
if Not AdoDataSet2.Loacte(Ryid,ls_ryid,[]) then
AdoDataSet2.Append;
for i:=0 to AdoDataSet2.Fields.Count-1 do
AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;
AdoDataSet1.Next;
end;
end;


这样很慢,原因有3:
1,对AdoDataSet1进行了所有记录的循环。
2,对AdoDataSet2进行了Loacte方法
3,对字段赋值进行了逐一字段的赋值: AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;

以上是问题所在,
谁能帮忙想想,有提高效率的更好方法吗?
...全文
454 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
xmfan 2007-08-12
  • 打赏
  • 举报
回复
ERR0RC0DE 是正解。还是用SQL效率高
podianliangshui 2007-08-12
  • 打赏
  • 举报
回复
sunware 是正解
liangyong007a 2007-08-10
  • 打赏
  • 举报
回复


很难用SQL实现,因为其中一个数据集是从客户端通过IAppserver接口的方法传递上来的,这是来此客户端本地的ACCESS数据库,现在这个比较是在中间层的服务器上的软件里进行的。
jin20000 2007-08-10
  • 打赏
  • 举报
回复
没道理用不了SQL,肯定可以间接使用SQL进行比较
sunware 2007-08-10
  • 打赏
  • 举报
回复
简单.既然已经定义了主键,那么默认该主键的值是唯一且已排序.

procedure AddAdoDataSet1toBuffer;
begin
//
end;

procedure PostBufferToAdoDataSet2;
begin
//
end;

procedure Compare2Tables;
begin
AdoDataSet1.First;
AdoDataSet2.First;
repeat
if AdoDataSet1.FieldbyName(Ryid).AsInteger = AdoDataSet2.FieldbyName(Ryid).AsInteger then begin
AdoDataSet1.Next;
AdoDataSet2.Next;
end else if AdoDataSet1.FieldbyName(Ryid).AsInteger > AdoDataSet2.FieldbyName(Ryid).AsInteger then begin
AdoDataSet2.Next
end else if AdoDataSet1.FieldbyName(Ryid).AsInteger < AdoDataSet2.FieldbyName(Ryid).AsInteger then begin
AddToBuffer;
AdoDataSet1.Next;
end;
until(AdoDataSet1.EOF);
PostBufferToAdoDataSet2;
end;

两个数据集各扫描一遍.
ziping 2007-08-10
  • 打赏
  • 举报
回复
个人以为用SQL语句比较好
baseyueliang 2007-08-10
  • 打赏
  • 举报
回复
当然,搂住可以尝试其他算法,比如先从数据集1中剔出掉所有的匹配记录,在把整个包追加到给数据集2的尾部。采用哪中算法,要看数据的特征的了。
baseyueliang 2007-08-10
  • 打赏
  • 举报
回复
还有,既然是主健,应该是值唯一的,在搜索到匹配记录时,应该避免下轮搜索。
baseyueliang 2007-08-10
  • 打赏
  • 举报
回复
如果需要插入很多记录(即有大量非匹配记录),建议用第3个数据集作缓存,等到找出所有非匹配记录后,再统一搬到数据集2种,这样就减少了搜索的循序次数。不过你的性能关键似乎不在此,因为你的数据显得并不太多,不知道ADoDataSet是内存数据集吗,在大量数据排序或计算时,我习惯用ClientDataSet,他内存级别的的,跟物理数据库没关系的。
bulletCoderHope 2007-08-10
  • 打赏
  • 举报
回复
假如记录数更多 ,你还是想在客户端的内存里去比较,那是没什么好办法的,除非你不使用内存。
ERR0RC0DE 2007-08-10
  • 打赏
  • 举报
回复
哦,最简单的方法是直接用SQL,开始是用楼主的思路做,才发现直接用SQL更明了。

insert into table2
select * from table1 t1
where not exists( select 1 from table2 where id = t1.id )
ERR0RC0DE 2007-08-10
  • 打赏
  • 举报
回复
就一关键字比较,然后将求并集的问题。

关键字比较最快是使用hash方法,查看贴子:
http://topic.csdn.net/t/20061018/21/5092570.html
强人的做法。

求并的方法就简单了,得到不存在的数据后,直接写个SQL:
insert into table2 (field1, field2....) select field1, field2... from table1 where id in (id1, id2, id3...)

这样最快了。
还adotable1.append....,比较晕人的法子。
yiyi0518 2007-08-10
  • 打赏
  • 举报
回复
说说我的想法:
1.新建中间容器
2.对该2个数据集根据某一列进行排序,然后根据该列值进行比对, 符合条件的插到中间容器
3.比对结束 把中间容器的值复制到目标容器
4.释放内存。

貌似以前《数据结构》里面学过这类算法
天行归来 2007-08-09
  • 打赏
  • 举报
回复
在记录集中处理,也只有此方法,效率肯定低下。
有些字段不是来自表,应该也还是有间接方法采用SQL进行数据合并?
brightyang 2007-08-09
  • 打赏
  • 举报
回复
帮顶
brightyang 2007-08-09
  • 打赏
  • 举报
回复
sf
peihexian 2007-08-09
  • 打赏
  • 举报
回复
楼主,你能select出来两个dataset,就不能直接select到两个临时表里?
到了临时表里以后insert into 2 where key_field not in (select key_field from xxx表) 不就得了?
hawk_e2e 2007-08-09
  • 打赏
  • 举报
回复
楼主目前的方法不是最快的。因为它的效率是O(n~2)。

下面的方法可以试验一下(因为我没试过):
1。不要用数据集的First、NEXT,研究一下ADODATASET.RECORDSET,用它访问数据集数据效率要快。
具体怎么用到网上找一下就知道了。
2.可以试一下两个ADODATASET都用主键做相同索引(ADODATASET里有个INDEXFIELDNAMES属性)。
用相同顺序互相对比。效率应该是O(n)。
xjq2003 2007-08-09
  • 打赏
  • 举报
回复
能不能用adoquery实现啊!!
liangyong007a 2007-08-09
  • 打赏
  • 举报
回复
现在最主要的慢的地方就是

for i:=0 to AdoDataSet2.Fields.Count-1 do
AdoDataSet2.Fields[i].value:=AdoDataSet1.Field[i].value;
AdoDataSet1.Next;


因为每次数据集的循环,都会对每个字段循环赋值。

谁能想到一个方法对AdoDataSet2和AdoDataSet1之间的字段赋值的其他办法?有不有直接把AdoDataSet1当前记录整个赋给AdoDataSet2,而不是一个一个字段赋值?如果能解决这个问题,估计速度将大大提速。
加载更多回复(2)

2,498

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧