首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

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

2012-03-08 
数据集比较的效率问题(超超级难题)AdoDataSet1和AdoDataSet2两个数据集结构一样,主键为字段Ryid,每个库均

数据集比较的效率问题(超超级难题)
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;

以上是问题所在,
谁能帮忙想想,有提高效率的更好方法吗?

[解决办法]
sf
[解决办法]
帮顶
[解决办法]
在记录集中处理,也只有此方法,效率肯定低下。
有些字段不是来自表,应该也还是有间接方法采用SQL进行数据合并?
[解决办法]
我有两个表也是比较回添,但用的是SQL处理,一个表两万条、另一个七千条,用了8分钟,速度慢4了
[解决办法]
想到几点,看看有没有帮助:
1。不要在遍历的过程中插入,在不改变任何内容的情况下遍历原数据集应该是很快的,这个时候使用一个TList记录下所有的书签;
2。遍历完后不要关闭数据集,读内存中的所有书签,然后再对目标数据集进行插入;
3。在循环开始处就用.Last读入所有目标数据集的记录,而记录没有改变的情况下,Locate的速度应该会比较快。
以上几点纯属猜想-___-b
[解决办法]
能不能用adoquery实现啊!!
[解决办法]
楼主目前的方法不是最快的。因为它的效率是O(n~2)。

下面的方法可以试验一下(因为我没试过):
1。不要用数据集的First、NEXT,研究一下ADODATASET.RECORDSET,用它访问数据集数据效率要快。
具体怎么用到网上找一下就知道了。
2.可以试一下两个ADODATASET都用主键做相同索引(ADODATASET里有个INDEXFIELDNAMES属性)。
用相同顺序互相对比。效率应该是O(n)。
[解决办法]
楼主,你能select出来两个dataset,就不能直接select到两个临时表里?
到了临时表里以后insert into 2 where key_field not in (select key_field from xxx表) 不就得了?
[解决办法]
假如记录数更多 ,你还是想在客户端的内存里去比较,那是没什么好办法的,除非你不使用内存。
[解决办法]
如果需要插入很多记录(即有大量非匹配记录),建议用第3个数据集作缓存,等到找出所有非匹配记录后,再统一搬到数据集2种,这样就减少了搜索的循序次数。不过你的性能关键似乎不在此,因为你的数据显得并不太多,不知道ADoDataSet是内存数据集吗,在大量数据排序或计算时,我习惯用ClientDataSet,他内存级别的的,跟物理数据库没关系的。

[解决办法]
还有,既然是主健,应该是值唯一的,在搜索到匹配记录时,应该避免下轮搜索。
[解决办法]
当然,搂住可以尝试其他算法,比如先从数据集1中剔出掉所有的匹配记录,在把整个包追加到给数据集2的尾部。采用哪中算法,要看数据的特征的了。
[解决办法]
个人以为用SQL语句比较好
[解决办法]
简单.既然已经定义了主键,那么默认该主键的值是唯一且已排序.

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;

两个数据集各扫描一遍.
[解决办法]
没道理用不了SQL,肯定可以间接使用SQL进行比较
[解决办法]
说说我的想法:
1.新建中间容器 
2.对该2个数据集根据某一列进行排序,然后根据该列值进行比对, 符合条件的插到中间容器
3.比对结束 把中间容器的值复制到目标容器
4.释放内存。

貌似以前《数据结构》里面学过这类算法
[解决办法]
就一关键字比较,然后将求并集的问题。

关键字比较最快是使用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....,比较晕人的法子。
[解决办法]
哦,最简单的方法是直接用SQL,开始是用楼主的思路做,才发现直接用SQL更明了。

insert into table2 
select * from table1 t1
where not exists( select 1 from table2 where id = t1.id )
[解决办法]
sunware 是正解
[解决办法]
ERR0RC0DE 是正解。还是用SQL效率高

热点排行