2

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

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

我的问题是:我能做些什么来加快速度,甚至花费更多的内存?查询的 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 会提高速度吗?

4

2 回答 2

3

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

  1. 执行查询以选择所有记录
  2. 在数据集上遍历一次,将记录复制到 TObjectList<TMyRecord> 的实例中,其中 TMyRecord 是可以包含数据集记录的所有字段的类;使您现在拥有的是对象列表中数据集的副本
  3. 如果可能,对列表进行排序(或选择正确排序),以便在需要时运行二进制搜索
  4. 释放数据集并仅在列表上工作。

在这种情况下,您将避免所有数据集开销,并且每次搜索都会更快。

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;
于 2013-08-02T12:31:34.007 回答
2

我认为在 a 中加载整个数据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';
于 2013-08-02T14:13:25.140 回答