是否有SQL聚合函数计算的标准?

时间:2012-10-13 20:50:43

标签: sql performance standards aggregate-functions

对于同一查询中对同一聚合函数的多次调用,SQL实现是否有标准?

例如,请考虑以下示例,基于流行的示例模式:

SELECT Customer,SUM(OrderPrice) FROM Orders
GROUP BY Customer
HAVING SUM(OrderPrice)>1000

据推测,计算SUM(OrderPrice)的值需要计算时间。这是针对聚合函数的每次引用产生的成本,还是为特定查询存储的结果?

或者,对于这种情况,SQL引擎实现没有标准吗?

1 个答案:

答案 0 :(得分:3)

虽然我已经使用过许多不同的DBMS,但我只会向您展示在SQL Server上证明这一点的结果。考虑这个查询,它甚至包括表达式中的CAST。查看查询计划,表达式sum(cast(number as bigint))仅采用一次,定义为DEFINE:([Expr1005]=SUM([Expr1006]))

set showplan_text on
select type, sum(cast(number as bigint))
from master..spt_values
group by type
having sum(cast(number as bigint)) > 100000

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  |--Filter(WHERE:([Expr1005]>(100000)))
       |--Hash Match(Aggregate, HASH:([Expr1004]), RESIDUAL:([Expr1004] = [Expr1004]) DEFINE:([Expr1005]=SUM([Expr1006])))
            |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0), [Expr1006]=CONVERT(bigint,[mssqlsystemresource].[sys].[spt_values].[number],0)))
                 |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]))

上面可能不是很明显,因为它没有显示SELECT结果,所以我在下面的查询中添加了*10。请注意,它现在包含一个额外的步骤DEFINE:([Expr1006]=[Expr1005]*(10))(步骤从下到上),这表明新表达式需要它执行额外的计算。然而,即使这是优化的,因为它不会重新计算整个表达式 - 仅仅是,它采用Expr1005并将其乘以10!

set showplan_text on
select type, sum(cast(number as bigint))*10
from master..spt_values
group by type
having sum(cast(number as bigint)) > 100000

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  |--Compute Scalar(DEFINE:([Expr1006]=[Expr1005]*(10)))
       |--Filter(WHERE:([Expr1005]>(100000)))
            |--Hash Match(Aggregate, HASH:([Expr1004]), RESIDUAL:([Expr1004] = [Expr1004]) DEFINE:([Expr1005]=SUM([Expr1007])))
                 |--Compute Scalar(DEFINE:([Expr1004]=CONVERT(nchar(3),[mssqlsystemresource].[sys].[spt_values].[type],0), [Expr1007]=CONVERT(bigint,[mssqlsystemresource].[sys].[spt_values].[number],0)))
                      |--Index Scan(OBJECT:([mssqlsystemresource].[sys].[spt_values].[ix2_spt_values_nu_nc]))

这很可能是所有其他DBMS的工作方式,至少考虑主要的那些,例如PostgreSQL,Sybase,Oracle,DB2,Firebird,MySQL。