查询或 dsum 中的 MS Access 性能 dlookup?

Posted

技术标签:

【中文标题】查询或 dsum 中的 MS Access 性能 dlookup?【英文标题】:MS Access performace dlookup on query or dsum? 【发布时间】:2010-08-13 14:23:50 【问题描述】:

我知道所有域聚合函数都很慢,但我正在寻找最小的弊端。

以下两个选项哪个更快?

    创建一个查询,该查询将按唯一值分组并对总数求和。使用 dlookup 从查询中获取我的总和。 在主表上执行 dsum,条件与选项 1 中的 GROUP BY 列相同?

编辑 1 我的问题是一个通用问题,我在很多情况下都想知道,但下面是目前正在考虑的具体情况。

在我的时间输入详细信息子表单中,我需要显示在这项工作中使用了多少材料。文本框的控制源如下所示:

=DLookUp("[SumOfPrice]","tm_materialsUsedByPart","[Part]=" & [cmbPart])

tm_materialsUsedByPart 当前是一个查询,它正在汇总所有使用的材料。

使用具有基本相同条件的 dsum 会更快,还是执行查询然后获取符合我的条件的单行会更快?

【问题讨论】:

【参考方案1】:
=DLookUp("[SumOfPrice]","tm_materialsUsedByPart","[Part]=" & [cmbPart])

没有看到 tm_materialsUsedByPart 的 SQL,我们只能猜测它在做什么。也许它会读取整个表或一组 JOINed 表,并使用 GROUP BY 将 Sum(Price) 聚合为 SumOfPrice。

对基础表进行 DSum 应该更快,尤其是在 [Part] 字段被索引的情况下。

=DSum("[Price]", "tblRowSource", "[Part]=" & Me.cmbPart)

这样,您要求数据库引擎仅读取包含您想要的 [Part] 值的行。您的 materialsUsedByPart 查询需要读取所有行,然后提取所需的单个组值。不要那样做。让数据库引擎读取尽可能少的行以获得所需的信息。

编辑:我错了,针对基表的 DSum 比针对聚合查询的 DLookup 更快。正如@Thomas 建议的那样,在我的简单测试中,这两种情况的查询计划都是相同的。

这是我的查询,qryMinutesPerClient

SELECT Time_Sub.CLIENT_ID, Sum(Time_Sub.MINUTES) AS SumOfMINUTES
FROM Time_Sub
GROUP BY Time_Sub.CLIENT_ID;

然后

DLookup("SumOfMINUTES","qryMinutesPerClient","CLIENT_ID = 11111")

这个查询计划的结果:

- Inputs to Query -
Table 'Time_Sub'
- End inputs to Query -

01) Restrict rows of table Time_Sub
      using rushmore
      for expression "Time_Sub.CLIENT_ID=11111"
02) Group result of '01)'

还有

DSum("MINUTES","Time_Sub","CLIENT_ID = 11111")

计划是一样的:

- Inputs to Query -
Table 'Time_Sub'
- End inputs to Query -

01) Restrict rows of table Time_Sub
      using rushmore
      for expression "CLIENT_ID=11111"
02) Group result of '01)'

最重要的性能问题涉及“使用 rushmore”,这是可能的,因为我的 CLIENT_ID 字段已编入索引。如果没有该索引,则无法在查询计划中使用 Rushmore,并且 DLookup 和 DSum 方法都明显比使用 Rushmore 慢。

【讨论】:

所以 MS Access 还不够智能,无法像我目前那样使用索引? [零件] 已编入索引。此外,您对 tm_materialsUsedByPart 查询的作用有一个很好的看法,它正在执行单个 JOIN。 我喜欢@Thomas 的建议,即在表单的记录源中包含总计,只要记录源可以是只读的,我就会这样做。如果您需要在时间条目详细信息子表单中编辑记录源值,请使用 DSum()。 Access 没有任何作用。但是 Jet/ACE 数据库引擎可以。如果您想了解它如何优化查询,您可以使用 Google SHOWPLAN,但这无助于了解域聚合函数的工作原理。通常,Jet/ACE(和域聚合函数)将使用所有索引,但有少数例外(例如不与子查询一起使用,有时它仅在比较的一侧使用索引)。【参考方案2】:

还有两个其他选项:相关子查询或派生表。相关子查询需要将查询中的列声明为自身为查询:

Select ...
 , ( Select Sum(Foo)
     From Bar
     Where Bar.FK = Gamma.PK ) As Total
From Gamma

在 Access 中,派生表将涉及创建一个保存的查询来执行所有总计,然后将该查询加入到您的主查询中。尽管可以在主查询中动态构建总计查询,但我的经验是,Access 对保存的查询和标准连接更满意。如果您向我们展示更多关于您要完成的工作,您可能会得到一些更具体的答案。

编辑

IMO,最快的解决方案是通过保存的查询将总数包含在表单的源中。即,不使用 DLookup 或 DSum,而是通过加入计算总计的查询将总计作为表单的 RecordSource 的一部分。

其次,要真正了解哪个函数的性能最好,您需要对数据进行一些性能测试。我的猜测是两者之间的性能相当。即使对存储的查询使用 DLookup,Access 也应该足够聪明,可以注入过滤条件,并实际上获得与使用 DSum 相当的执行计划。

最后,如果您要使用域聚合函数,并且 DLookup 中使用的查询的唯一目的是为此表单提供总计,那么 IMO,使用 DSum 更有意义,因为它使您的意图域聚合函数的使用对读者来说更清楚。

【讨论】:

我添加了编辑 1。希望这会让我的要求更清楚。 我无法将该字段添加到表单的记录源,因为表单数据需要可编辑。在记录源中使用 GROUP BY 查询将不允许数据可编辑。 @jeffreymb - 记录源中不需要分组依据。如果您使用已保存的查询,则只有已保存的查询具有分组依据。主查询不会。如果您在记录源中使用关联子查询,则只有它有一个分组依据,而不是主查询。

以上是关于查询或 dsum 中的 MS Access 性能 dlookup?的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL 在 Ms-access 查询中运行 Total

MS Access SQL 运行总数

访问:DSUM 行为怪异

SQLServer中的交叉查询

提高计算 MS-Access 中大型数据集 7 天滚动平均值的查询的性能

MS Access 中的加入或子查询