【问题标题】:Fastest way to locate record in TQuery resultset在 TQuery 结果集中找到记录的最快方法
【发布时间】:2011-08-08 11:20:45
【问题描述】:

我想知道最好(阅读:最快)的方法是在 Tquery SQL 语句的结果集中找到一条记录。

到目前为止,我一直在使用 TQuery.Locate,如果我是对的,那是唯一可用于在结果集中搜索的语句。那么我们该如何优化呢?

我有一些想法,但还没有时间在大型数据集上比较它们:

假设我们有一个包含以下字段的表:

Create Table aTable (
 ID int, 
 Name1 varchar(50), 
 Name2 varchar(50));

还有以下查询:

SELECT ID, Name1, Name2 from aTable

我们想在结果集中通过它的 ID 来定位一条记录

  • 如果 aTable 在 ID 上有索引,定位会更快吗?
  • 如果我在 SQL 语句中添加“Order By ID”,定位会更快吗?

对此有什么想法吗?

[编辑] 澄清其用途:查询由 Reportbuilder Dataview 执行,然后通过数据管道(即 TQuery.Dataset)提供。在自定义报告中,我需要根据一些更高级别的 ID 遍历管道。所以不使用查询在这里不适用。我只是想知道我上面的任何建议是否会加快速度。

【问题讨论】:

  • Locate 在客户端执行。所以在最坏的情况下,需要首先从数据库中获取整个结果集。如果客户端创建在 WHERE 子句中包含 ID 的 SQL 会快得多,这只会获取一条记录。
  • 是否将“按 ID 排序”添加到您的选择并不重要,因为如果 ID 是 PK,那么 DB 引擎将通过 PK 列的索引获取结果行。
  • @Justme - 所以原始表中的索引会对 TQuery.Locate 语句产生影响?
  • @Bascy 我没有这么说。如您所见,没有“order by”的选择与“order by PK column”相同。换句话说,在这种情况下,查询的自然计划与索引读取一样快。是的 - 你应该在 ID 上有索引 - 如果你将 ID 设为 PK,它就会创建

标签: delphi reportbuilder nexusdb


【解决方案1】:

以下是一些您可能会觉得有用的提示

  • 仅在索引列上使用 Locate() 方法
  • 在索引列上使用“排序依据”
  • 在打开查询之前使用准备
  • 使用 DisableControls / EnableControls
  • 根据需要使用升序/降序索引(或同时使用两者)
  • 试试 FastReports

如果您有大型数据集的主/详细信息,请不要获取所有详细信息记录 - 换句话说 - 不要使用本地主详细信息 - 让数据库引擎只为您提供所需的记录。

【讨论】:

  • 我在哪里可以找到关于 TQuery.Locate() 如何以及为什么在索引列上更好地工作的任何信息?
  • 我不认为 Locate 使用数据库索引。在我的例子中,在数据库中定位一个有 800k 记录的记录需要 5 - 10 秒。如果我在 SQL 命令中使用 where 子句定位记录,执行速度非常快(不到 1 秒)。使用 Locate 的另一个效果是我的应用程序的内存使用量增加了 1 GB 以上。也许 Locate 使用索引,但效率很低 - 在我看来,它是在第一次调用期间创建索引(而不是使用数据库)。后续调用要快得多。
【解决方案2】:

如果您需要经常对大型数据集执行此操作,您最好将数据集转换为记录数组并在索引字段上实现一些自定义搜索例程。

【讨论】:

  • 索引字段上的自定义搜索例程如何比 db 更快?
  • 在 ReportBuilder 中,您无法访问像记录数组这样的纯 Delphi 代码,而只能访问子 Delphi(和慢速)脚本引擎。
  • 实际上与我们相反;-) 报告模板是在设计时创建的,其他所有内容(数据视图、管道、表格等)都是在运行时 Delphi 中创建的
  • @Bascy 为什么要在运行时创建这些?
  • @JustMe 这与我在这里提出的问题无关
【解决方案3】:

您应该添加一个 ID 进行搜索,以便仅检索预期的行。

在 ReportBuilder Data 视图中,转到 Query Designer,然后转到 Search 选项卡,然后添加一个带有“自动搜索”选项。

然后转到 ReportBuilder Calc 视图,从菜单中选择“视图/事件”。点击“报表对象”树视图中的报表根项,然后双击“OnGetAutoSearchValues”并检索预期值:

var
    Fld : TppAutoSearchField;
    i   : integer;     
begin
  for i:=0 to Report.AutoSearchFieldCount-1 do
  begin
   Fld := Report.AutoSearchFields[i];

    if Fld<>nil then
    begin    
      if (Fld.FieldName='FIRST_PARAM') then 
      begin
        Fld.SearchExpression := .....;
      end
      else if (uppercase(Fld.FieldName)='2ND_PARAM') then
      begin 
        Fld.SearchExpression := intToStr(...);
      end;
    end;
  end;  
end;

【讨论】:

  • reportbuilder 报告在此阶段 100% 以 Delphi 代码生成,使用设计时创建的报告模板。模板使用的数据视图和管道是在运行时生成的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-10
  • 2015-04-15
  • 2020-11-12
  • 1970-01-01
  • 2011-01-09
  • 2016-07-02
相关资源
最近更新 更多