我有一个有5000万条记录的表,但它是一个紧凑的结构(id,int1,int 1,int 2,int 3)。所有相关指标均已落实。
对于每个用户交互,我需要查询大约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会提高速度吗?
考虑到将整个表加载到内存中不是问题,我建议:
- 执行查询以选择所有记录
- 在数据集上行走一次以将记录复制到TObjectList<TMyRecord>,其中TMyRecord是可以包含数据集记录的所有字段的类;使其成为对象列表中数据集的副本
- 如果可能,对列表进行排序(或按正确顺序选择),以便在需要时运行二进制搜索
- 释放数据集并仅处理列表
在这种情况下,您将避免所有数据集开销,每次搜索都会更快。
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;
我认为在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';