【问题标题】:Is there a standard for SQL aggregate function calculation?SQL聚合函数计算有标准吗?
【发布时间】:2012-10-04 07:41:00
【问题描述】:

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

例如,考虑以下基于流行示例架构的示例:

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

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

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

【问题讨论】:

    标签: sql performance standards aggregate-functions


    【解决方案1】:

    虽然我使用过许多不同的 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 的工作方式,至少考虑到主要的 DBMS,即 PostgreSQL、Sybase、Oracle、DB2、Firebird、MySQL。

    【讨论】:

      猜你喜欢
      • 2016-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 1970-01-01
      • 2017-03-23
      • 1970-01-01
      相关资源
      最近更新 更多