Еквівалент SQL Server пункту Oracle USING INDEX


9

Чи є еквівалент SQL Server 2008 клавіші USING INDEX в Oracle? Конкретно для конструкції:

CREATE TABLE c(c1 INT, c2 INT);
CREATE INDEX ci ON c (c1, c2);
ALTER TABLE c ADD CONSTRAINT cpk PRIMARY KEY (c1) USING INDEX ci;

У документації на сервер Sql про унікальні індекси зазначено (наголос додано):

Унікальні індекси реалізуються наступними способами:

ПЕРШИЙ КЛЮЧ або єдине обмеження

Коли ви створюєте обмеження PRIMARY KEY, унікальний кластерний індекс на стовпчику або стовпцях автоматично створюється, якщо кластерний індекс у таблиці ще не існує і ви не вказуєте унікальний некластеризований індекс . Стовпець первинного ключа не може дозволити значення NULL.

Що, мабуть, означає, що існує спосіб визначення конкретного індексу для первинного ключа.


Просто визначте ПК разом із таблицею. create table c (c1 int not null primary key, c2 int)
a_horse_with_no_name

Мене зацікавила саме частина "створення ПК за допомогою названого індексу".
nik

Ні, немає способу це зробити. Первинний ключ - обмеження та індекс. У тому, що ви надали, основний ключ за замовчуванням буде унікальним кластерним індексом. Що б зробило інший визначений індекс дублікатом, якщо ви не включили як c1, так і c2 в пункт де.
Аарон

Відповіді:


7

Чи є еквівалент SQL Server 2008 клавіші USING INDEX в Oracle?

Ні. Коли ви створюєте первинний ключ або унікальне обмеження в SQL Server, унікальний індекс для підтримки цього обмеження створюється автоматично, з тими ж ключами.

Що, мабуть, означає, що існує спосіб визначення конкретного індексу для первинного ключа.

Ні. Документація намагається лише пояснити, чи буде створений автоматичний підтримуючий індекс як кластеризований чи некластеризований, якщо ви не вказуєте. Це заплутано сформульовано, я згоден.

Для уточнення, коли ви додаєте обмеження первинного ключа до існуючої таблиці без вираження переваг, підтримуючий індекс буде кластеризований, якщо в таблиці немає попереднього кластерного індексу. Підтримка індексу буде створена як некластеризована, якщо вже є кластерний індекс

Ви можете спеціально запросити кластерний або некластеризований первинний ключ, використовуючи: PRIMARY KEY CLUSTEREDабо PRIMARY KEY NONCLUSTERED.

Справедливо кажучи, документація на цю тему набагато чіткіша:

table_constraint (Transact-SQL)


5

Синтаксис 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%%значення представляють сторінки самого індексу.

Результати:

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.