Синтаксис SQL Server для создания кластерного индекса, который также является первичным ключом:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Что касается вашего комментария: «заставить PK использовать именованный индекс», приведенный выше код приведет к тому, что индекс первичного ключа будет назван «PK_c».
Первичный ключ и ключ кластеризации не обязательно должны быть одинаковыми столбцами. Вы можете определить их отдельно. В приведенном выше примере измените CLUSTERED
ключевое слово на NONCLUSTERED
, а затем просто добавьте кластерный индекс, используяCREATE INDEX
синтаксис:
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);
В SQL Server кластеризованный индекс - это таблица, они одно и то же. Кластерный индекс определяет логический порядок строк, хранящихся в таблице. В моем первом примере, строки хранятся в порядке значений c1
и c2
столбцов. Поскольку ключ кластеризации также определяется как первичный ключ, комбинацияc1
и c2
должна быть уникальной для всей таблицы.
Во втором примере, первичный ключ состоит из c1
и c2
столбцов, однако ключ кластеризации является только c2
столбец. Поскольку я не указал UNIQUE
атрибут в CREATE INDEX
заявлении, ключ кластеризации (c2
) не обязательно должен быть уникальным по всей таблице. «Uniquifier» будет автоматически создан SQL Server и добавлен к значениям в c2
столбце для создания ключа кластеризации. Этот ключ кластеризации, поскольку он теперь уникален, будет затем использоваться в качестве идентификатора строки в других индексах, созданных в таблице.
Чтобы доказать, что ключ кластеризации контролирует расположение строк в хранилище, вы можете использовать недокументированную функцию fn_PhysLocCracker(%%PHYSLOC%%)
. Следующий код показывает, что строки располагаются на диске в порядке c2
столбца, который я определил как ключ кластеризации:
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;
Результаты из моей базы данных:
На изображении выше первые три столбца выводятся из fn_PhysLocCracker
функции, показывая физическое упорядочение строк на диске. Вы можете видеть, что slot_id
значение увеличивает шаг блокировки со c2
значением, которое является ключом кластеризации. Индекс первичного ключа хранит строки в другом порядке, что можно увидеть, заставив SQL Server возвращать результаты сканирования первичного ключа:
SELECT pkt.c1
, pkt.c2
FROM dbo.PKTest pkt WITH (INDEX = PK_PKTest, FORCESCAN);
Обратите внимание, я не использовал ORDER BY
предложение в приведенном выше утверждении, так как я пытаюсь показать порядок элементов в индексе первичного ключа.
Выходные данные из вышеприведенного запроса:
Что касается fn_PhysLocCracker
функции, мы можем видеть физический порядок индекса первичного ключа.
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;
Поскольку мы читаем исключительно из самого индекса, то есть в запросе нет ссылок на столбцы вне индекса, %%PHYSLOC%%
значения представляют страницы в самом индексе.
Результаты:
create table c (c1 int not null primary key, c2 int)