2013-04-14 41 views
5

在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

回答

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)

0

OVER子句集合函数发射的实际行数可以如下所示:从表AS x INNER JOIN(选择分区列,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的部分中找到。