Синтаксис SQL Server для створення кластерного індексу, який також є первинним ключем:
CREATE TABLE dbo.c
(
c1 INT NOT NULL,
c2 INT NOT NULL,
CONSTRAINT PK_c
PRIMARY KEY CLUSTERED (c1, c2)
);
Що стосується Вашого коментаря: "зробити ПК використовувати названий індекс", вищевказаний код призведе до того, що індекс первинного ключа буде названий "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
) не повинен бути унікальним у таблиці. 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;
Результати мого tempdb:
На зображенні вище, перші три стовпці виводяться з 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)