2013-04-14 10 views
5

Tabellenstruktur mit einem geclusterten eindeutigen Index für Empno.Wie generiert diese Abfrage zwei Joinoperatoren im Ausführungsplan?

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] 

Abfrage

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

Query Plan

enter image description here

Antwort

3

Pläne mit Fenster Aggregate normalerweise eine gemeinsame Unter Ausdruck Spule verwenden. Eine gute aufzuschreiben dieser Art von Plan ist hier Partitioning and the Common Subexpression Spool

der Tabelle Nehmen wir die folgenden Zeilen hat

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) 

Es verfügt über 6 Zeilen insgesamt mit 2 verschiedenen EMPNO Werte. Der tatsächliche Ausführungsplan, der die tatsächliche Anzahl der ausgegebenen Zeilen zeigt, ist darunter.

enter image description here

Der Iterator-Segment an der Spitze des Plans fügt ein Flag in den Zeilen, die durch ihn angibt, übergeben, wenn es der Beginn einer neuen Partition ist (das heißt der empno geändert hat).

Der Spool zu seiner unmittelbaren Linken (primäre Spool) ruft eine Reihe nach dem Segment-Iterator und fügt es in eine Arbeitstabelle in Tempdb ein. Sobald das Flag angezeigt wird, dass eine neue Gruppe gestartet wurde, wird eine Zeile an die oberste Eingabe des Nested Loop-Operators zurückgegeben.

Dies bewirkt, dass der Strom Aggregat über die Zeilen in dem Arbeitstisch (Sekundärspule im Plan) aufgerufen wird, wird die SUM([SAL]) berechnet dann wird dieser Wert mit den Zeilen in dem Arbeitstisch (den dritte Spule Operator verbunden wieder der Plan), bevor die Arbeitstabelle für die neue Gruppe abgeschnitten wird.

Die primäre Segment Spule emittiert einen Scheinzeile, um die endgültige Gruppe verarbeitet zu erhalten, weshalb die tatsächliche Anzahl von Reihen ausgesendet wird, wie 3 (Anzahl der Gruppen plus eins) gezeigt

0

Aggregatfunktionen mit OVER Klausel kann so umgeschrieben werden: FROM Tabelle AS x INNER JOIN (SELECT Partitionsspalten, AggregateWithoutOverClause (...) ... FROM ...) AS y ON x.PartitionColumns = y.PartitionColumns (wenn Partitionsspalten obligatorisch sind - NOT NULL).

Beispiel:

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; 

Ergebnisse:

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. 

Ausführungspläne: enter image description here

Dies wird erklären, nur die letzten beitreten: enter image description here

Die Erklärung für die erste Verbindung finden Sie im Abschnitt Per-Gruppenbearbeitung/Partitioning and the Common Subexpression Spool.