Lassen Sie uns eine Million Zeilen zusammen mit einigen Spalten in eine temporäre Tabelle werfen:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (PK)
);
INSERT INTO #174860 WITH (TABLOCK)
SELECT RN
, RN % 1000
, RN % 10000
FROM
(
SELECT TOP 1000000 ROW_NUMBER () OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values v1,
master..spt_values v2
) t;
CREATE INDEX IX_174860_IX ON #174860 (COL1) INCLUDE (COL2);
Hier habe ich einen Clustered-Index (standardmäßig) für die PK
Spalte. Es gibt einen nicht gruppierten Index COL1
, der eine Schlüsselspalte von COL1
und enthält COL2
.
Betrachten Sie die folgende Abfrage:
SELECT *
FROM #174860
WHERE PK >= 15000 AND PK < 15005
AND COL2 = 5000;
Hier benutze ich nicht, BETWEEN
weil Aaron Bertrand um diese Frage herumhängt.
Wie sollte SQL Server Optimizer diese Abfrage? Nun, ich weiß, dass der Filter PK
die Ergebnismenge auf fünf Zeilen reduziert. SQL Server kann den Clustered-Index verwenden, um zu diesen fünf Zeilen zu springen, anstatt alle Millionen Zeilen in der Tabelle zu lesen. Der Clustered-Index enthält jedoch nur die PK-Spalte als Schlüsselspalte. Sobald die Zeile in den Speicher eingelesen ist, müssen wir den Filter anwenden COL2
. Hier PK
ist ein Suchprädikat und COL2
ist ein Prädikat.
SQL Server findet fünf Zeilen unter Verwendung des Suchprädikats und reduziert diese fünf Zeilen mit dem normalen Prädikat auf eine Zeile.
Wenn ich den Clustered-Index anders definiere:
CREATE TABLE #174860 (
PK INT NOT NULL,
COL1 INT NOT NULL,
COL2 INT NOT NULL,
PRIMARY KEY (COL2, PK)
);
Und führen Sie die gleiche Abfrage aus, ich erhalte unterschiedliche Ergebnisse:
In diesem Fall kann SQL Server beide Spalten in der WHERE
Klausel verwenden. Mit den Schlüsselspalten wird genau eine Zeile aus der Tabelle gelesen.
Betrachten Sie für ein weiteres Beispiel diese Abfrage:
SELECT *
FROM #174860
WHERE COL1 = 500
AND COL2 = 3545;
Der IX_174860_IX-Index ist ein Deckungsindex, da er alle für die Abfrage erforderlichen Spalten enthält. Es ist jedoch nur COL1
eine Schlüsselspalte. SQL Server kann mit dieser Spalte suchen, um die 1000 Zeilen mit einem übereinstimmenden COL1
Wert zu finden. Diese Zeilen in der COL2
Spalte können weiter gefiltert werden , um die endgültige Ergebnismenge auf 0 Zeilen zu reduzieren.