此查询如何在执行计划中生成两个连接运算符?

时间:2013-04-14 06:18:26

标签: sql-server sql-server-2008 join sql-execution-plan

在empno上具有聚簇唯一索引的表结构。

CREATE TABLE [dbo].[EMP](
    [EMPNO] [int] NOT NULL,
    [ENAME] [varchar](10) NULL,
    [JOB] [varchar](9) NULL,
    [MGR] [int] NULL,
    [HIREDATE] [datetime] NULL,
    [SAL] [int] NULL,
    [COMM] [int] NULL,
    [DEPTNO] [int] NULL
) ON [PRIMARY]

查询

SELECT sal,sum(sal) over(PARTITION BY empno)
FROM emp

查询计划

enter image description here

2 个答案:

答案 0 :(得分:3)

使用窗口聚合的计划通常使用公共子表达式假脱机。在这里Partitioning and the Common Subexpression Spool

可以很好地写出这类计划

假设该表具有以下行

CREATE TABLE [dbo].[EMP](
    [EMPNO] [int] NOT NULL,
    [SAL] [int] NULL) 

INSERT INTO [dbo].[EMP] 
VALUES (1,1),
       (1,2), 
       (1,3),
       (1,4), 
       (2,1),
       (2,2)

它总共有6行,有2个不同的EMPNO值。显示实际发出的行数的实际执行计划如下。

enter image description here

计划顶部的段迭代器为通过它的行添加一个标志,指示它何时是新分区的开始(即empno已更改)。

直接左侧的线轴(主线轴)从段迭代器一次获取一行,并将其插入tempdb中的工作表中。一旦获得标志说新组已经启动它就会返回一行到嵌套循环运算符的顶部输入。

这会导致在工作表中的行(计划中的辅助假脱机)上调用流聚合,计算SUM([SAL]),然后将此值与工作表中的行连接起来(第三个工作表被截断为新组准备好之前的计划中的假脱机操作符。

主段假脱机发出虚拟行以便处理最后一组,这就是为什么实际发出的行数显示为3(组数加1)

答案 1 :(得分:0)

可以重写具有OVER子句的聚合函数:FROM table AS x INNER JOIN(SELECT partition columns,AggregateWithoutOverClause(...)... FROM ...)AS y ON x.PartitionColumns = y .PartitionColumns(如果分区列是必需的 - NOT NULL)。

示例:

SET STATISTICS IO ON;
SET NOCOUNT ON;

-- OP's query
SELECT sal,sum(sal) over(PARTITION BY empno) 
FROM emp;

-- Reqwriten query
SELECT a.sal, b.SumSal
FROM emp a
INNER JOIN (SELECT EMPNO, SUM(sal) AS SumSal FROM emp GROUP BY EMPNO) b ON a.EMPNO = b.EMPNO;

结果:

sal         
----------- -----------
1           10
2           10
3           10
4           10
1           3
2           3

Table 'Worktable'. Scan count 3, logical reads 21, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'EMP'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

sal         SumSal
----------- -----------
1           10
2           10
3           10
4           10
1           3
2           3

Table 'Worktable'. Scan count 3, logical reads 21, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
Table 'EMP'. Scan count 1, logical reads 2, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

执行计划: enter image description here

这将仅解释上次加入enter image description here

第一次加入的说明可在每组处理/ Partitioning and the Common Subexpression Spool部分找到。