2010-08-13 157 views
0

我知道所有的域聚合函数都很慢,但我正在寻找最少的问题。查询或dsum MS Access性能查询?

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

  1. 创建一个查询,该查询将按唯一值进行分组并总和。有dlookup从查询中获得我的总和。
  2. 在主表上做一个dsum,其标准与我在选项1中的GROUP BY列相同?

编辑1
我的问题是,我在很多场合都知道一个普通的问题,但下面是正在考虑具体的情况现在。

在我的时间输入详细子表单上,我需要显示此作业中使用了多少材料。对于文本框控件来源是这样的:

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

tm_materialsUsedByPart目前正在总结中使用的所有材料的查询。

使用具有本质上相同标准的dsum会更快吗?还是更快地执行查询,然后获取符合我的标准的单行?

+0

添加了示例.. – Icode4food 2010-08-13 15:26:37

回答

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

没有看到tm_materialsUsedByPart的SQL,我们只能猜测它在做什么。也许它会读取整个表格或一组JOIN表格,并使用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慢显着

+0

因此,即使我目前正在使用索引,MS Access的智能性还不足以使用索引? [部分]被索引。另外,你对'tm_materialsUsedByPart'查询做了什么很好的观点,它正在做一个JOIN。 – Icode4food 2010-08-13 15:53:09

+1

我喜欢@Thomas的建议,将总数包含在表单的记录源中,只要记录源可以是只读的,我就会这样做。如果您需要编辑时间条目明细子表单中的记录源值,请使用DSum()。 – HansUp 2010-08-13 16:05:26

+0

访问不会执行任何操作。但是Jet/ACE数据库引擎的确如此。如果您想了解如何优化查询,那么可以使用Google SHOWPLAN,但这无助于弄清楚域聚合函数的工作方式。通常,Jet/ACE(和域聚合函数)将使用所有索引,但有一些例外(例如,不用于子查询,有时仅在比较的一侧使用索引)。 – 2010-08-14 03:53:00

1

还有两个选项:相关子查询或派生表。相关子查询将带来宣布在查询到自己的列是一个查询:

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

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

EDIT

IMO,最快的解决方案将是包括总,通过已保存的查询,在源的形式。即,不使用DLookup或DSum,而是通过加入计算总计的查询来将总数作为表单的RecordSource的一部分。其次,要真正知道哪个函数的性能最好,您需要对数据进行一些性能测试。我的猜测是两者之间的表现会相当。即使DLookup针对存储的查询,Access也应该足够智能,以注入过滤标准,并实际上获得使用DSum的类似执行计划。

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

+0

我添加了编辑1.希望这会让我更清楚我在问什么。 – Icode4food 2010-08-13 15:25:24

+0

我无法将该字段添加到表单的记录源,因为表单数据需要可编辑。在记录源中有一个GROUP BY查询将不允许数据是可编辑的。 – Icode4food 2010-08-13 15:55:52

+1

@jeffreymb - 你不需要在记录源中的一个组。如果您使用已保存的查询,则只有已保存的查询将具有该组。主查询不会。如果您在记录源中使用相关子查询,则只有它具有一组而不是主查询。 – Thomas 2010-08-13 17:05:03