在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;

解决方案 »

  1.   

    楼主,一个表里有70万条数据,第二个表里有10万。
    循环对比,这不就是一个笛卡尔积么? 70W*10W,不慢才怪啊。
    即使索引做的再好,你依然要遍历两个表N次。从业务逻辑优化吧,楼主说说业务逻辑。
    基本思路就是减少表中的遍历,减小循环。
      

  2.   

    呵呵,是的,的确是70万*10万,而且从逻辑上貌似没什么好修改的,业务是比对两个表里字符串的相似度,比如表1里有一条数据是jggowgwo3r34,表2里有一条数据是jggowgwo3r3k,比较出有11个相同位置的字符相同。
      

  3.   

    使用sql函数实现 两个字符串的相似度 比较函数
    直接在sql里比较
    但是这样也要比较70万x10万次!所以,最好能发明一个新的 字符串取特征函数,返回一个整型
    先对70万、10万条记录生成对应的特征值,建立索引
    再比较就飞快了
      

  4.   

    ProgressBar.Position:=ProgressBar.Position+1;
    Application.ProcessMessages;
    可以优化为每100行才执行一次越循环越慢,是不是因为70万行全部加载到客户端的内存里,就慢了?
    机器多少内存,程序最多会占多少内存?
      

  5.   

    10万级循环,多一行代码,效率就降低很多,如果无法在SQL内部完成(存储过程或者扩展存储过程),那么就研究这段代码的本身的效率,可以照楼上说的,改成100次执行一次大体上讲,可以将10万的小库直接缓存到内存中,然后关闭,基本上可以大大提高效率了,ADOTable 换成只有一个字段的AdoQuery,
    然后
    Mt_No:=ADOTable_MT.FieldByName('MT_No').AsString;
    就可以换成
    ADOQuery_MT.Fields[0].AsString;
    这样效率上肯定会提高的,至于能否流畅,没底,呵呵.如果你够大胆,可以考虑2线程,一个从数据库组件读字符串到内存池,另一个线程负责比较,不过在控制同步时就非常非常讲究了,否则达不到效果.
      

  6.   

    ADOQuery_MT.Fields[0].AsString
    呵呵,楼上的,我已经使用了这个方法,但是效果不明显,我两个表都是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;
      

  7.   

    这个思路应该值得一试。
    或者起多个线程,每个线程10W的量和另外个表比较。注意:每个线程要有单独的连接。另外:“select * from” 可否改为只查询需要的字段,这样加载到内存的数据少很多,速度也会提高不少。
      

  8.   

    小的那个表载入内存并hash,保证飞快。
      

  9.   

    sql server里自定义一个比较函数,用select 内联查询
      

  10.   

    你的做法循环确实多!能不能这样做:
    1、首选将10万条数据,也就是数据最少的那个表中的数据都查询出来,做为循环!
    2、循环10万条数据,每条数据到数据库中查询一次(就是比较相近的字符串),或者是执行一个SQL的函数或存储过程来实现这个比对算法。
    3、将70万数据库要比对的字符串做索引,查询用这个字符串应该会快一些!这样只循环10万次就可以,但是消耗效率的地方应该在比对这里了。这样我觉得应该比你双层循环快一些,因为第二个不是循环,只是做一个查询。当然这只是一个想法,具体还要看你是如何比对字符串的!