在SQL_SERVER里有两个表,第一个表里有70万条数据,第二个表里有10万条数据,这两个表分别用两个ADOTABLE连接,用了两个循环,对查询到的数据进行比对,速度很慢,就是不比对,仅仅完成这个循环就要很长时间,请问有没有快点的方法?代码如下:var
I,K,L,Count_No:Integer;
Mt_No,Base_No:String;
begin
ADOTable_MT.First;
ProgressBar.Max:=ADOTable_MT.RecordCount-1;
for I := 0 to ADOTable_MT.RecordCount-1 do
begin
ProgressBar.Position:=ProgressBar.Position+1;
Application.ProcessMessages;
Mt_No:=ADOTable_MT.FieldByName('MT_No').AsString;
//=========================================================================
ADOTable.First;
ProgressBar1.Max:=ADOTable.RecordCount-1;
for K := 0 to ADOTable.RecordCount-1 do
//for K := 0 to 100 do
begin
ProgressBar1.Position:=ProgressBar1.Position+1;
Base_No:=ADOTable.FieldByName('28recd').AsString; //#######################################################################
{比对的过程}
//#######################################################################
ADOTable.Next;
end;
//=========================================================================
ADOTable_MT.Next;
end;end;
I,K,L,Count_No:Integer;
Mt_No,Base_No:String;
begin
ADOTable_MT.First;
ProgressBar.Max:=ADOTable_MT.RecordCount-1;
for I := 0 to ADOTable_MT.RecordCount-1 do
begin
ProgressBar.Position:=ProgressBar.Position+1;
Application.ProcessMessages;
Mt_No:=ADOTable_MT.FieldByName('MT_No').AsString;
//=========================================================================
ADOTable.First;
ProgressBar1.Max:=ADOTable.RecordCount-1;
for K := 0 to ADOTable.RecordCount-1 do
//for K := 0 to 100 do
begin
ProgressBar1.Position:=ProgressBar1.Position+1;
Base_No:=ADOTable.FieldByName('28recd').AsString; //#######################################################################
{比对的过程}
//#######################################################################
ADOTable.Next;
end;
//=========================================================================
ADOTable_MT.Next;
end;end;
循环对比,这不就是一个笛卡尔积么? 70W*10W,不慢才怪啊。
即使索引做的再好,你依然要遍历两个表N次。从业务逻辑优化吧,楼主说说业务逻辑。
基本思路就是减少表中的遍历,减小循环。
直接在sql里比较
但是这样也要比较70万x10万次!所以,最好能发明一个新的 字符串取特征函数,返回一个整型
先对70万、10万条记录生成对应的特征值,建立索引
再比较就飞快了
Application.ProcessMessages;
可以优化为每100行才执行一次越循环越慢,是不是因为70万行全部加载到客户端的内存里,就慢了?
机器多少内存,程序最多会占多少内存?
然后
Mt_No:=ADOTable_MT.FieldByName('MT_No').AsString;
就可以换成
ADOQuery_MT.Fields[0].AsString;
这样效率上肯定会提高的,至于能否流畅,没底,呵呵.如果你够大胆,可以考虑2线程,一个从数据库组件读字符串到内存池,另一个线程负责比较,不过在控制同步时就非常非常讲究了,否则达不到效果.
呵呵,楼上的,我已经使用了这个方法,但是效果不明显,我两个表都是select * from这样查询全部的,应该都调到内存了吧,还是很慢,没多大的改观,具体代码如下:
var
I,K,L,Count_No:Integer;
Mt_No,Base_No:String;
begin
ADOQuery_MT.First;
ProgressBar.Max:=ADOQuery_MT.RecordCount-1;
for I := 0 to ADOQuery_MT.RecordCount-1 do
begin
ProgressBar.Position:=ProgressBar.Position+1;
Application.ProcessMessages;
//Mt_No:=ADOQuery_MT.FieldByName('MT_No').AsString;
Mt_No:=ADOQuery_MT.Fields[1].AsString;
//=========================================================================
ADOQuery_base.First;
ProgressBar1.Max:=ADOQuery_base.RecordCount-1;
for K := 0 to ADOQuery_base.RecordCount-1 do
//for K := 0 to 100 do
begin
ProgressBar1.Position:=ProgressBar1.Position+1;
Base_No:=ADOQuery_base.Fields[1].AsString; //#######################################################################
{}
//#######################################################################
ADOQuery_base.Next;
end;
//=========================================================================
ADOQuery_MT.Next;
end;
end;
或者起多个线程,每个线程10W的量和另外个表比较。注意:每个线程要有单独的连接。另外:“select * from” 可否改为只查询需要的字段,这样加载到内存的数据少很多,速度也会提高不少。
1、首选将10万条数据,也就是数据最少的那个表中的数据都查询出来,做为循环!
2、循环10万条数据,每条数据到数据库中查询一次(就是比较相近的字符串),或者是执行一个SQL的函数或存储过程来实现这个比对算法。
3、将70万数据库要比对的字符串做索引,查询用这个字符串应该会快一些!这样只循环10万次就可以,但是消耗效率的地方应该在比对这里了。这样我觉得应该比你双层循环快一些,因为第二个不是循环,只是做一个查询。当然这只是一个想法,具体还要看你是如何比对字符串的!