Die SQL Server-Syntax zum Erstellen eines Clustered-Index, der auch ein Primärschlüssel ist, lautet:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Was Ihren Kommentar betrifft: "Eine PK einen benannten Index verwenden lassen", führt der obige Code dazu, dass der Primärschlüsselindex "PK_c" heißt.
Der Primärschlüssel und der Clusterschlüssel müssen nicht dieselben Spalten sein. Sie können sie separat definieren. Ändern Sie im obigen Beispiel das CLUSTERED
Schlüsselwort in NONCLUSTERED
und fügen Sie dann einfach einen Clustered-Index mit der folgenden CREATE INDEX
Syntax hinzu:
CREATE TABLE dbo.c
(
c1 INT,
c2 INT,
CONSTRAINT PK_c
PRIMARY KEY NONCLUSTERED (c1, c2)
);
CREATE CLUSTERED INDEX CX_c ON dbo.c (c2);
In SQL Server der Clustered - Index ist der Tisch, sie sind ein-und-die-gleiche. Ein Clustered-Index definiert die logische Reihenfolge der in der Tabelle gespeicherten Zeilen. In meinem ersten Beispiel werden Zeilen in der Reihenfolge der Werte der Spalten c1
und gespeichert c2
. Da der Clustering-Schlüssel auch als Primärschlüssel definiert ist, muss die Kombination von c1
und c2
tabellenweit eindeutig sein.
Im zweiten Beispiel besteht der Primärschlüssel aus den Spalten c1
und c2
, der Clustering-Schlüssel ist jedoch nur die c2
Spalte. Da ich das UNIQUE
Attribut in der CREATE INDEX
Anweisung nicht angegeben habe , muss der Clustering-Schlüssel ( c2
) nicht in der gesamten Tabelle eindeutig sein. Ein "Eindeutiger" wird automatisch von SQL Server erstellt und an die Werte in der c2
Spalte angehängt , um den Clustering-Schlüssel zu erstellen. Dieser Clustering-Schlüssel wird, da er jetzt eindeutig ist, als Zeilen-ID in anderen in der Tabelle erstellten Indizes verwendet.
Um zu beweisen, dass der Clustering-Schlüssel das Layout der im Speicher befindlichen Zeilen steuert, können Sie die undokumentierte Funktion verwenden fn_PhysLocCracker(%%PHYSLOC%%)
. Der folgende Code zeigt, dass die Zeilen in der Reihenfolge der c2
Spalte, die ich als Clustering-Schlüssel definiert habe , auf der Festplatte angeordnet sind :
USE tempdb;
CREATE TABLE dbo.PKTest
(
c1 INT NOT NULL
, c2 INT NOT NULL
, c3 VARCHAR(256) NOT NULL
);
ALTER TABLE PKTest
ADD CONSTRAINT PK_PKTest
PRIMARY KEY NONCLUSTERED (c1, c2);
CREATE CLUSTERED INDEX CX_PKTest
ON dbo.PKTest(c2);
TRUNCATE TABLE dbo.PKTest;
INSERT INTO dbo.PKTest (c1, c2, c3)
SELECT TOP(25) o1.object_id / o2.object_id, o2.object_id, o1.name + '.' + o2.name
FROM sys.objects o1
, sys.objects o2
WHERE o1.object_id >0
and o2.object_id > 0;
SELECT plc.file_id
, plc.page_id
, plc.slot_id
, pk.*
FROM dbo.PKTest pk
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;
Die Ergebnisse meiner Tempdb sind:
In der Abbildung oben werden die ersten drei Spalten von der fn_PhysLocCracker
Funktion ausgegeben und zeigen die physische Reihenfolge der Zeilen auf der Festplatte. Sie können sehen, dass der slot_id
Wert den Sperrschritt mit dem Wert erhöht c2
, der der Clustering-Schlüssel ist. Der Primärschlüsselindex speichert Zeilen in einer anderen Reihenfolge. Dies lässt sich feststellen, indem SQL Server gezwungen wird, Ergebnisse vom Scannen des Primärschlüssels zurückzugeben:
SELECT pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);
Beachten Sie, dass ich ORDER BY
in der obigen Anweisung keine Klausel verwendet habe, da ich versuche, die Reihenfolge der Elemente im Primärschlüsselindex anzuzeigen.
Die Ausgabe der obigen Abfrage lautet:
Wenn fn_PhysLocCracker
wir uns die Funktion ansehen, können wir die physikalische Reihenfolge des Primärschlüsselindex sehen.
SELECT plc.file_id
, plc.page_id
, plc.slot_id
, pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN)
CROSS APPLY fn_PhysLocCracker(%%PHYSLOC%%) plc;
Da wir ausschließlich aus dem Index selbst lesen, dh in der Abfrage keine Spalten außerhalb des Index referenziert werden, %%PHYSLOC%%
repräsentieren die Werte die Seiten im Index selbst.
Die Ergebnisse:
create table c (c1 int not null primary key, c2 int)