了解 SQL 服务器执行计划
Understanding a SQL Server execution plan
我有以下查询,我正在使用它来查看 SQL 服务器执行计划。
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
计划如下:
我对这个计划有几个问题:
- 为什么它在聚合之前进行排序?
- 这两个Stream Aggregate 操作是做什么用的?我可以理解在加入后做一个,但为什么要做两个?
- 最后,两个“Compute Scalar”有什么用?当我将鼠标悬停在它们上面时,我希望它能告诉我类似“这是
CASE
语句”的内容,但它们非常不透明。我怎么知道“计算标量”在做什么?
- 为什么它在聚合之前进行排序?
流聚合要求输入按 group by
列排序。这样它就可以一起接收一个组的所有行,并且可以在看到它已经完成了对它的所有行的处理时发出该组的聚合总数(并重置下一组的聚合)。
- 这两个流聚合操作是做什么用的?我可以理解在加入后做一个,但为什么要做两个?
SQL服务器可以做的一项优化是在连接前进行部分聚合以减少进入连接的行数,然后在连接后计算最终总数。如果 fact
有三行 division = 'west'
,它可以将其折叠到 1
行并传递值 3
。然后它只需要在内部连接的 table 中进行一次查找而不是 3 次。然后它可以对连接结果求和以获得最终总数(即如果 division
有 2 个匹配行。SUM
3
和 3
是 6
)
在 SSMS select 运算符中查看“属性”window (F4) 以查看两个流聚合的“定义值” .
联接右边的那个有表达式
[partialagg1008] = Scalar Operator(Count(*))
而join后的有
[globalagg1009] = Scalar Operator(SUM([partialagg1008]))
- 最后,两个“Compute Scalar”有什么用?当我将鼠标悬停在它们上面时,我希望它能告诉我一些类似“这是
CASE
语句”的信息,但它们非常不透明。我如何知道“计算标量”在做什么?
您也需要查看这些定义的值。
其中一个具有表达式 [Expr1006] = Scalar Operator(CONVERT_IMPLICIT(int,[globalagg1009],0))
并且正在将 COUNT
聚合的结果转换回 int
。在内部 COUNT
和 COUNT_BIG
使用与 returns bigint
相同的设备 - 对于 COUNT
这需要强制转换以获得最终公布的数据类型。
另一个正在计算您的 CASE
表达式的结果并且具有表达式 [Expr1007] = Scalar Operator(CASE WHEN [avails].[dbo].[fact].[Division]=N'east' THEN 'XXX' ELSE 'YYY' END)
我有以下查询,我正在使用它来查看 SQL 服务器执行计划。
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
计划如下:
我对这个计划有几个问题:
- 为什么它在聚合之前进行排序?
- 这两个Stream Aggregate 操作是做什么用的?我可以理解在加入后做一个,但为什么要做两个?
- 最后,两个“Compute Scalar”有什么用?当我将鼠标悬停在它们上面时,我希望它能告诉我类似“这是
CASE
语句”的内容,但它们非常不透明。我怎么知道“计算标量”在做什么?
- 为什么它在聚合之前进行排序?
流聚合要求输入按 group by
列排序。这样它就可以一起接收一个组的所有行,并且可以在看到它已经完成了对它的所有行的处理时发出该组的聚合总数(并重置下一组的聚合)。
- 这两个流聚合操作是做什么用的?我可以理解在加入后做一个,但为什么要做两个?
SQL服务器可以做的一项优化是在连接前进行部分聚合以减少进入连接的行数,然后在连接后计算最终总数。如果 fact
有三行 division = 'west'
,它可以将其折叠到 1
行并传递值 3
。然后它只需要在内部连接的 table 中进行一次查找而不是 3 次。然后它可以对连接结果求和以获得最终总数(即如果 division
有 2 个匹配行。SUM
3
和 3
是 6
)
在 SSMS select 运算符中查看“属性”window (F4) 以查看两个流聚合的“定义值” .
联接右边的那个有表达式
[partialagg1008] = Scalar Operator(Count(*))
而join后的有
[globalagg1009] = Scalar Operator(SUM([partialagg1008]))
- 最后,两个“Compute Scalar”有什么用?当我将鼠标悬停在它们上面时,我希望它能告诉我一些类似“这是
CASE
语句”的信息,但它们非常不透明。我如何知道“计算标量”在做什么?
您也需要查看这些定义的值。
其中一个具有表达式 [Expr1006] = Scalar Operator(CONVERT_IMPLICIT(int,[globalagg1009],0))
并且正在将 COUNT
聚合的结果转换回 int
。在内部 COUNT
和 COUNT_BIG
使用与 returns bigint
相同的设备 - 对于 COUNT
这需要强制转换以获得最终公布的数据类型。
另一个正在计算您的 CASE
表达式的结果并且具有表达式 [Expr1007] = Scalar Operator(CASE WHEN [avails].[dbo].[fact].[Division]=N'east' THEN 'XXX' ELSE 'YYY' END)