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

时间:2010-08-13 14:23:51

标签: performance ms-access

我知道所有域聚合函数都很慢,但我正在寻找最少的邪恶。

以下两个选项中哪个更快?

  1. 创建一个查询,该查询将按唯一值进行分组并将总和相加。让dlookup从查询中得到我的总和。
  2. 在主表上使用与选项1中的GROUP BY列相同的条件进行复制吗?
  3. 编辑1
    我的问题是我在许多情况下都想知道的一般性问题,但下面是目前正在考虑的具体情况。

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

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

    tm_materialsUsedByPart目前是一个查询,总结了所有使用的材料。

    使用具有完全相同标准的dsum或执行查询更快,然后获取符合我标准的单行会更快吗?

2 个答案:

答案 0 :(得分:1)

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

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 :(得分: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慢明显