【发布时间】:2014-03-26 15:11:45
【问题描述】:
在我在工作中构建的一个应用程序中,我有一个大型数据库,其中有一个表说“人”,有 100,000 多行。此外,此表中的条目包含两种类型的数据: 父类型和子类型,其中每个子类型条目在特殊的“Child_OF”列中具有其父级的数据库 ID。
在内存中,两种 db 条目类型都由相应的类“TParent”和“TChild”表示,其中每个父类都有字段“children : TList”。
使用 ADO 最快的方法是: - 创建父母列表并正确分配他们的孩子...
在我看来……可以通过以下方式解决问题 1)批量(通过一个sql查询)从表中检索所有父母并创建带有空子列表的父母列表。 2)批量检索所有孩子,并为每个父母尝试从相应的数据集中找到他/她的孩子。
这是我对程序分配阶段的想法的一个例子......
procedure assignParentsTheirChildren(parentList: TList<TParent>;
ma_people: TADOTable);
var
i: Integer;
qry: TADOQuery;
aChild: TChild;
aParent: TParent;
begin
// create the query
qry := TADOQuery.Create(nil);
qry.Connection := ma_people.Connection;
// set the sql statement to fetch all children ...
qry.SQL.Clear;
qry.SQL.Add('Select * from ' + ma_people.TableName + ' WHERE ChildOF <> ' +
QuotedStr(''));
// supposedly do some optimization---
qry.CursorLocation := clUseClient; // load whole recordset in memory
qry.DisableControls;
// disable controls ensures that no dataset bound control will be updated while iterating the recordset
qry.CursorType := ctStatic; // set cursor to static
// open dataset
qry.Open;
// ***EDIT*** for completeness I add the suggestion made by Agustin Seifert below
qry.RecordSet.Fields['ChildOf'].Properties.Item['Optimize'].value := true;
for i := 0 to parentList.count - 1 do
begin
// get daddy
aParent := parentList[i];
qry.Filter := 'ChildOF = ' + QuotedStr(IntToStr(aParent.parentID));
qry.Filtered := true;
while (not qry.EOF) do
begin
aChild := TChild.Create;
getChildFromQuery(aChild, qry); // fills in the fields of TChild class...
aParent.children.Add(aChild);
qry.Next;
end;
end;
qry.Free;
end;
我猜上述代码的最大瓶颈是我正在为每个新父母过滤数据。使用 seek() 或 locate/find... 是否有更快的返工?基本上可以假设我的数据集是静态的(在创建父母列表期间)并且网络延迟无限:)(也就是说,我首先想从内存中将孩子分配给父母)。 非常感谢!
顺便说一句,我使用的是 Microsoft SQL Server 2012。
【问题讨论】:
-
你真的需要一次将所有的父母和孩子都加载到内存中吗?您可以实现延迟加载机制,只需使用最少的信息填充父列表,然后在需要时加载扩展的详细信息(如子信息)。
-
@Andy_D 是的.. 不幸的是,我需要同时为所有的父母和孩子工作。
标签: performance delphi ado