我意识到我的查询每次使用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似乎都在再次执行子查询,无论这是否正确,避免时间成本的最佳做法是什么?
上面的例子只是以最基本的方式表示问题
TL;DR:不,这是完全错误的
当您在SQL Server中运行查询时,优化器会将其编译为它能找到的最有效的方法。您可以通过单击SSMS中的Include Actual Execution Plan
来查看结果。
对于您指定的查询,它通常会执行以下操作:
- 它注意到子查询可以内联到查询中,并且这样做:
SELECT sub.a, SUM(sub.b), SUM(sub.c)
FROM temp
GROUP BY a;
然后,它通过
a
值评估聚合表的最佳方式。假设根本没有索引,这里很可能会选择Hash Aggregate
。在执行时,每一行都被馈送到Hash中,Hash构建了一个内存中的哈希表,以
a
值为键。每一行都是基于a
查找的,如果以前从未见过,则会向哈希表中添加一个键。然后CCD_ 6和CCD_。假设您在
a,b,c
上有一个索引。现在有了一种更快的方法,称为Stream Aggregate,因为现在值通过按a
排序的Aggregate。每一行都通过聚合。如果
a
的值与前一行相同,那么它的b
和c
的值将添加到我们迄今为止所拥有的值中。当a
值发生变化时,将输出现有结果,然后我们再次开始聚合。
确实,对额外的列求和是额外的开销,但与读取磁盘表或哈希相比,这相当小,因为整个查询只进行一次哈希。