首页 > 解决方案 > 如何使用 SQL Server SUM 函数避免指数时间成本?

问题描述

我意识到每次使用 SUM 函数时我的查询都需要指数级的时间......

例如,下面的代码需要 2 秒

SELECT sub.a, SUM(sub.b)
FROM (
   SELECT a, b, c 
   FROM temp
)sub 
GROUP BY a;

现在使用第二个 SUM 需要 4 秒,依此类推......

SELECT sub.a, SUM(sub.b), SUM(sub.c)
FROM (
   SELECT a, b, c 
   FROM temp
)sub 
GROUP BY a;

似乎我所做的每个 SUM 都会再次执行子查询,这是否正确,避免时间成本的最佳做法是什么?

上面的例子只是以最基本的方式表示问题

标签: sumsql-server-2008-r2query-optimization

解决方案


TL;DR:不,这是完全错误的。

当您在 SQL Server 中运行查询时,优化器会将其编译成它可以找到的最有效的方法。您可以通过单击Include Actual Execution PlanSSMS 来查看结果。

对于您指定的查询,它通常会执行以下操作:

  1. 它指出子查询可以内联到查询中,并且这样做:
SELECT sub.a, SUM(sub.b), SUM(sub.c)
FROM temp
GROUP BY a;
  1. 然后它评估按a值聚合表的最佳方法。假设根本没有索引,Hash Aggregate这里很可能会选择 a。

  2. 在执行时,每一行都被输入到 Hash 中,它建立了一个内存中的哈希表,其中a值作为键。每一行都基于 查找a,如果之前没有看到过,则将一个键添加到哈希表中。然后将值添加bc该键。

  3. 假设您在a,b,c. 现在可以使用更快的方法,称为 Stream Aggregate,因为现在值正在通过按 排序的 Aggregate a

  4. 每行都通过聚合。如果该a值与之前的行相同,则将其bc值添加到我们目前所拥有的任何内容中。当a值发生变化时,输出现有结果,我们再次开始聚合。

确实,对额外的列求和是额外的开销,但与读取磁盘表或散列表相比,它非常小,每个查询只执行一次。


推荐阅读