理解SQL Server执行计划:Sort、Stream Aggregate等操作相关疑问
你提供的查询语句如下:
SELECT TOP 1000 fact.division, case when fact.division='east' then 'XXX' else 'YYY' end div, count(1) FROM division join fact on (division.division=fact.division) where fact.division!='east' group by fact.division
对应的执行计划示意图:
问题1:为什么聚合操作前会先执行Sort操作?
SQL Server的Stream Aggregate算子要求输入数据集必须按照分组列有序,才能按顺序连续读取同分组的行完成聚合,不需要额外内存缓存分组哈希表。
你的查询按fact.division分组,而join后的结果集没有按该列排序的索引支撑,所以优化器会在流聚合前插入Sort算子,将结果集按分组列排序,适配流聚合的执行要求。
问题2:为什么会有两个Stream Aggregate操作?
这是SQL Server优化器的预聚合优化策略:
- 第一个Stream Aggregate是在fact表完成过滤后、join操作前执行,先按
fact.division做一次局部聚合统计计数,大幅减少需要参与join的行数,降低join阶段的IO和计算开销 - 第二个Stream Aggregate是在join完成后,对关联后的结果做最终的全局聚合,合并预聚合的计数结果
这种拆分比直接将所有明细行join后再做一次聚合的性能高很多,是典型的关联场景下的聚合优化手段。
问题3:两个Compute Scalar操作的作用是什么?如何查看具体计算逻辑?
两个Compute Scalar分别对应不同阶段的标量计算:
- 第一个一般位于预聚合阶段之后,用于计算预聚合输出的衍生值(比如计数的中间常量转换)
- 第二个位于最终聚合之后,用于执行你查询中写的
CASE WHEN逻辑,生成div列的输出值,因为该列不需要参与分组和关联,只需要在最终输出前计算即可。
如果悬浮提示信息模糊,你可以右键点击对应的Compute Scalar算子,选择「属性」,在属性面板中找到定义的值(Defined Values) 选项,展开后就能看到该算子所有输出列对应的完整计算表达式,所有计算逻辑都可以明确查到。
内容的提问来源于stack exchange,提问作者David542
相关产品推荐
相关产品推荐

