sql первинний ключ та індекс


106

Скажімо, у мене є рядок ідентифікатора (int) у наборі бази даних в якості основного ключа. Якщо я запитую ідентифікатор часто, мені також потрібно його індексувати? Або це тим, що є первинним ключем, означає, що він уже індексований?

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

Редагувати: додаткове запитання - чи заподіє шкода додатково індексувати первинний ключ?

Відповіді:


73

Ви маєте рацію, це заплутано, що SQL Server дозволяє створювати дублікати індексів у тих самих полях. Але той факт, що ви можете створити інший, не означає, що індекс ПК також не існує.

Додатковий індекс не приносить користі, але єдиною шкодою (дуже невеликою) є додатковий розмір файлу та накладні витрати на створення рядків.


39
Пошкодження невикористаних індексів справді дуже шкідливі. З одного боку, індекси накопичують сховище. Інша справа, це сповільнює написання та оновлення. Завжди видаляйте індекси, які не збираються використовувати.
Печер'є

50

Як уже говорили всі, первинні ключі автоматично індексуються.

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

Наприклад, у вас є таблиця з багатьма стовпцями, але ви запитуєте лише стовпці з ідентифікатором, іменем та адресою. Беручи ідентифікатор як основний ключ, ми можемо створити наступний індекс, побудований на ідентифікаторі, але включає стовпці Ім'я та Адреса.

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

Отже, коли ви використовуєте цей запит:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server дасть вам результат лише за допомогою створеного вами індексу, і він нічого не прочитає з фактичної таблиці.


28

ПРИМІТКА. Ця відповідь стосується розвитку корпоративного класу в цілому .

Це проблема RDBMS, а не лише SQL Server, і поведінка може бути дуже цікавою. Для одного, хоча для первинних ключів прийнято автоматично (однозначно) індексуватися, він НЕ є абсолютним. Бувають випадки, коли важливо, щоб первинний ключ НЕ був однозначно індексований.

У більшості RDBMS, унікальний індекс автоматично буде створений на первинному ключі, якщо його ще не існує . Отже, ви можете створити власний індекс у стовпці первинного ключа, перш ніж оголосити його первинним ключем, тоді цей індекс буде використаний (якщо прийнятний) двигуном бази даних, коли ви застосуєте декларацію первинного ключа. Часто ви можете створити первинний ключ і дозволити створювати його унікальний індекс за замовчуванням, потім створити власний альтернативний індекс у цьому стовпці, а потім скинути індекс за замовчуванням.

Тепер для цікавої частини - коли ви НЕ хочете унікального індексу первинного ключа? Ви не хочете його і не можете терпіти, коли ваша таблиця набере достатньо даних (рядків), щоб зробити обслуговування індексу занадто дорогим. Це залежить від обладнання, механізму RDBMS, характеристик таблиці та бази даних та завантаженості системи. Однак він зазвичай починає проявлятися, коли таблиця досягає кількох мільйонів рядків.

Основна проблема полягає в тому, що кожна вставка рядка або оновлення стовпця первинного ключа призводить до сканування індексу, щоб забезпечити унікальність. Це унікальне сканування індексів (або його еквівалент в залежності від RDBMS) стає значно дорожчим у міру зростання таблиці, поки воно не домінує над роботою таблиці.

Я багато разів займався цим питанням із таблицями розміром у два мільярди рядків, 8 ТБ пам’яті та сорок мільйонів рядкових вставок на день. Мені було доручено переробити відповідну систему, яка включала випадання унікального індексу первинного ключа практично як перший крок. Дійсно, падіння цього індексу було необхідним у виробництві просто для відновлення після відключення, перш ніж ми навіть наблизилися до перепроектування. Цей редизайн включав пошук інших способів забезпечити унікальність первинного ключа та забезпечити швидкий доступ до даних.


Що робити, якщо ключ - це ключ для автоматичного збільшення int або bigint? Чи достатньо розумний SQL Server, щоб не робити унікального сканування в цьому випадку?
квеллер

1
@quillbreaker: IDENTITYполе не гарантує бути унікальним. Зрештою, користувачі можуть вставити повторювані значення, якщо вони користувачі IDENTITY_INSERT.

Я знаю, що це давня тема, але я не розумію, яким чином однозначне сканування одного індексу було б таким навантаженням на систему. Сканування дерева B + має бути O (log n) * v, де v обмежений накладними витратами для фрагментації індексу, недосконалого балансу дерева тощо. Таким чином, 2 мільярди рядків будуть базою журналів 2 з 2 000 000 000 (приблизно 31 прагнення) разів, скажімо, 2 або 3 або навіть 10. 40M вставок на день - це близько 462 / сек, ~ 100 IO на вкладку ... Ahh ... О. Я бачу. І це було раніше поширених SSD.
Чарльз Бернс

Якщо б ви не скинули обмеження унікальності, не став би накладніші витрати на перевірку кожного з рядків на унікальність?
Макс Кандокія

20

Первинні ключі завжди індексуються за замовчуванням.

Ви можете визначити первинний ключ у SQL Server 2012 за допомогою SQL Server Management Studio або Transact-SQL. Створення первинного ключа автоматично створює відповідний унікальний, кластеризований або некластеризований індекс.

http://technet.microsoft.com/en-us/library/ms189039.aspx


9

Ось уривок з MSDN :

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


8

PK стане кластерним індексом, якщо не вказати некластеризовані


3

Оголошення PRIMARY KEYабо UNIQUEобмеження призводить до того, що SQL Server автоматично створює індекс.

Унікальний індекс можна створити без відповідності обмеженням, але обмеження (первинний або унікальний) не може існувати без унікального індексу.

Звідси створення обмеження:

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

і одночасно скидання обмеження знизить пов'язаний індекс.

Отже, чи існує фактична різниця між PRIMARY KEYабо UNIQUE INDEX:

  • NULLзначення не дозволені в PRIMARY KEY, але дозволені в UNIQUEіндексі; і як у операторів набору (UNION, EXCEPT, INTERSECT), тут NULL = NULLзначить, що ви можете мати лише одне значення, оскільки два NULLs знаходять як дублікати один одного;
  • PRIMARY KEYв таблиці може існувати лише один, тоді як можна створити 999 унікальних індексів
  • коли PRIMARY KEYстворюється обмеження, воно створюється як кластеризоване, якщо в таблиці вже не є кластерний індекс або NONCLUSTEREDне використовується його визначення; коли UNIQUEіндекс створюється, він створюється так, як NONCLUSTEREDтільки він не є специфічним, CLUSTEREDа такого вже немає;

2

Зробивши його первинним ключем, слід також автоматично створити для нього індекс.


1

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

Наприклад: поля A, B, C є первинним ключем, тому, коли ви робите запит на основі цих 3 полів у вашому КЛАЗУ, де продуктивність хороша, АЛЕ, коли ви хочете запитувати з полем лише C на місці, де клауза, ви не будете отримувати хороші показники. Таким чином, щоб активізувати продуктивність, вам потрібно буде індексувати поле C вручну.

Більшу частину часу ви не побачите проблему, поки не наберете більше 1 мільйона записів.


0

У мене величезна база даних без (окремого) індексу.

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


Це тому, що PK - це кластерний індекс, подивіться на свій план запитів
SQLMenace

0

первинні ключі автоматично індексуються

ви можете створювати додаткові індекси за допомогою ПК, залежно від використання

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