最快查询反复大表的方法

时间:2013-08-02 10:21:41

标签: delphi delphi-xe unidac

我有一个包含5000万条记录的表,但是结构紧凑(id,int1,int1,int2,int3)。所有相关指标都已实施。

我需要为每次用户交互查询大约50次。使用针对数据库服务器的常规准备查询大约需要5秒钟。所有查询都是简单的选择。

我的问题是:我能做些什么来加快这个速度,甚至花费更多的内存?查询的Locate方法不够灵活,直接在查询中使用过滤器的速度很慢。

我正在运行的主要查询是

select knowledge_id, knowledge_family_id, tag_level, tag_order, 
  total_title_direct_words, total_title_parenthesis_words from knowledge_tags 
  where dictionary_word_id = XX order by tag_level, tag_order

有人可以提出策略吗? TVirtualTable会提高速度吗?

2 个答案:

答案 0 :(得分:3)

考虑到将整个表加载到内存中不是我建议的问题:

  1. 执行查询以选择所有记录
  2. 一次遍历数据集,将记录复制到TObjectList< TMyRecord>的实例中,其中TMyRecord是可以包含数据集记录的所有字段的类;现在你所拥有的就是对象列表中数据集的副本
  3. 如果可能,请对列表进行排序(或选择正确排序的列表),以便在需要时运行二进制搜索
  4. 释放数据集,仅在列表中使用。
  5. 在这种情况下,您将避免所有数据集开销,每次搜索都会快得多。

    TMyRecord的一个例子是:

    interface
    
    type
      TMyRecord = class
      private
        FId: Integer;
        FCol1: Integer;
        FCol2: Integer;
        FCol3: Integer;
        FCol4: Integer;
      public
        constructor Create(aId, aCol1, aCol2, aCol3, aCol4: Integer);
        property Id: Integer read FId write FId;
        property Col1: Integer read FCol1 write FCol1;
        property Col2: Integer read FCol2 write FCol2;
        property Col3: Integer read FCol3 write FCol3;
        property Col4: Integer read FCol4 write FCol4;
      end;
    
    implementation
    
    constructor TMyRecord.Create(aId, aCol1, aCol2, aCol3, aCol4: Integer);
    begin
      FId := aId;
      FCol1 := aCol1;
      FCol2 := aCol2;
      FCol3 := aCol3;
      FCol4 := aCol4;
    end;
    

答案 1 :(得分:2)

我认为在TClientDataSet中加载整个数据会更快,并使用FINDKEY来查找这些记录。

要使用FindKey(),您必须定义如下索引:

Cds.IndexDefs.ADD('IDX1', 'FieldA;FieldB',[]);
Cds.IndexName := 'IDX1';
if Cds.FindKey([A,B]) then begin
  //Do something
end;

您还可以创建多个索引并随时使用它:

Cds.IndexDefs.ADD('IDX1', 'FieldA;FieldB',[]);
Cds.IndexDefs.ADD('IDX2', 'FieldD;FieldB',[]);
Cds.IndexDefs.ADD('IDX3', 'FieldA;FieldC',[]);  

if SeekAB then 
  Cds.IndexName := 'IDX1'
else if SeekDB then 
  Cds.IndexName := 'IDX2'
else 
  Cds.IndexName := 'IDX3';