Чи повинні кластерні індекси бути унікальними?


83

Що станеться, якщо кластерний індекс не є унікальним? Чи може це призвести до поганої роботи, оскільки вставлені рядки переходять на якусь сторінку "переповнення"?

Чи він "зроблений" унікальним, і якщо так, то як? Який найкращий спосіб зробити його унікальним?

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

Дякую!

Відповіді:


90

Вони не повинні бути унікальними, але це, безумовно, заохочується.
Я ще не стикався зі сценарієм, коли я хотів створити CI на не унікальному стовпці.

Що станеться, якщо ви створите CI на не унікальному стовпці

Якщо кластерний індекс не є унікальним індексом, SQL Server робить усі повторювані ключі унікальними, додаючи внутрішньо сформоване значення, яке називається унікальним ідентифікатором

Це призводить до поганої роботи?

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

  • Скільки даних містить таблиця.
  • Яка швидкість вставок.
  • Як часто використовується CI у виборі (коли не існує індексів охоплення, майже завжди).

Редагуйте
, на що вказував Ремус у коментарях, існують випадки використання, коли створення не унікального ІС було б розумним вибором. Я, який не стикався з одним із цих сценаріїв, просто свідчить про свою відсутність впливу чи компетентності (виберіть свій вибір).


30
+1, тому що все, що ви говорите, є правильним, але я просто хотів додати: не-унікальний CI є досить поширеним явищем, коли сканування діапазону для певного (не-унікального) стовпця є переважним шаблоном доступу.
Ремус Русану,

@Remus Ruşanu: Я був думати про додавання заяви про відмову до моєї заяви сценарію , як , але це нічого не означає . Дякуємо, що вказали сценарій, коли він може бути корисним.
Lieven Keersmaekers

4
@Remus: отже, ви маєте на увазі нішеву ситуацію, коли у вас є не унікальний стовпець, такий як 'Departmentid', де ви запитуєте щось на зразок 'DepartmentId BETWEEN 1 and 100'? редагувати ах Я бачу, що ви маєте на увазі, так, стовпець дати в таблиці реєстрації також є хорошим прикладом.
littlegreen

Гей, у мене є таблиця потоку подій, де існує кілька рядків з однаковим "AggregateId", який є стовпцем для типу GUID. Єдині запити, що виконуються в таблиці, - це отримання всіх подій для даного AggregateId. Цікаво, це кластеризований індекс чи некластеризований індекс?
Shayan C

@ShayanC - Якщо продуктивність пошуку є вашою основною метою, я б зробив це CI, щоб, ймовірно, заощадити на введенні вводу при отриманні всіх рядків для даного ідентифікатора. Як і у всіх сценаріях продуктивності, єдиним надійним способом є вимірювання.
Lieven Keersmaekers

32

Мені подобається перевіряти, що говорить Королева індексації Кімберлі Трипп на цю тему:

Я почну з моєї рекомендації щодо кластеризаційного ключа - з кількох причин. По-перше, це легке рішення, а по-друге, прийняття цього рішення на ранніх термінах допомагає попереджати попередження деяких типів фрагментації. Якщо ви можете запобігти певним типам фрагментації базової таблиці, тоді ви можете мінімізувати деякі заходи технічного обслуговування (деякі з яких у SQL Server 2000 І менше, у SQL Server 2005) вимагають, щоб ваша таблиця була в режимі офлайн. Добре, я перейду до реконструкції пізніше .....

Почнемо з ключових речей, які я шукаю в кластеризаційному ключі:

* Unique
* Narrow
* Static

Чому унікальний? Ключ кластеризації повинен бути унікальним, оскільки кластеризаційний ключ (коли такий існує) використовується як ключ пошуку з усіх некластеризованих індексів. Візьмемо, наприклад, індекс на звороті книги - якщо вам потрібно знайти дані, на які вказує запис індексу - цей запис (запис індексу) повинен бути унікальним, інакше запис індексу буде тим, який ви шукаєте ? Отже, коли ви створюєте кластерний індекс - він повинен бути унікальним. Але SQL Server не вимагає, щоб ваш ключ кластеризації створювався в унікальному стовпці. Ви можете створити його в будь-якому стовпці, який хочете. Якщо внутрішньо ключ кластеризації не є унікальним, тоді SQL Server «уніфікує» його, додавши до даних 4-байтове ціле число. Отже, якщо кластерний індекс створюється на чомусь, що не є унікальним, тоді при створенні індексу не тільки виникають додаткові накладні витрати, але й втрачається дисковий простір,

Джерело: постійно зростаючі ключові дебати щодо кластеризації - знову!


Питання, однак, Queen рекомендує newsequentialid для уніфікації даних, але SQL Server генерує власний уніфікатор, якщо ви не вказали його. Чи існує тоді ще якась причина для додавання власного послідовного ідентифікатора?
littlegreen

2
@littlegreen: вона каже, що якщо ви наполягаєте на використанні GUID (які насправді дуже погані для використання в індексі кластеризації), то принаймні використовуйте, newsequentialid()щоб отримати майже послідовний GUID. Але так: якщо ви додаєте свій власний унікальний ідентифікатор (я завжди віддаю перевагу INT IDENTITY), тоді у вас є це значення під рукою, і ви можете використовувати його (наприклад, для встановлення відносин FK). Додані SQL Server унікальні файли невидимі для вас, і, отже, вони лише накладні витрати, якими ви не можете скористатися.
marc_s

Розумію. Ну, це буде аргументом на користь кластерного індексу (CompanyID, DepartmentID, id INT IDENTITY) замість лише перших двох. Дякую!
littlegreen

1
@littlegreen: ще краще - зробіть свій кластерний індекс лише (ID INT IDENTITY), а інші поля - за потреби - в окремий, некластеризований індекс. Кластеризований індекс повинен бути якомога меншим - врешті-решт, кластеризовані стовпці індексу також додаються до кожного запису кожного і кожного некластеризованого індексу в цій таблиці - тому не витрачайте свої байти з широким кластеризованим індекс!
marc_s

1
Так, але тоді я втрачаю вигоду від того, що всі дані мого відділу групуються, і я можу вставити / видалити / отримати цілий відділ відразу. Мої дані будуть розпорошені, а вставлення / видалення цілих підрозділів або навіть цілих компаній буде повільним. Мої запити виконуються лише в одній компанії відразу, і часто потрібно оновлювати цілий набір даних.
littlegreen

9

Чи повинні кластерні індекси бути унікальними?

Вони цього не роблять, і бувають випадки, коли краще, якщо вони ні.

Розглянемо таблицю з напіввипадковим, унікальним ідентифікатором EmployeeId та ідентифікатором DepartmentId для кожного працівника: якщо ваше твердження select

SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%

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


Чи є у вас довідки?

Там же кластерний індекс Design Guidelines , наприклад, в якому говориться,

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

  • Може використовуватися для часто використовуваних запитів.
  • Забезпечують високий ступінь унікальності.
  • Може використовуватися в запитах діапазону.

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


Так, це те, про що я думав дотепер, але я також отримую прямо протилежну пораду, тому цікаво, що це правда. Чи є у вас довідки?
littlegreen

@littlegreen Я відредагував свою відповідь, щоб спробувати відповісти на ваше запитання.
ChrisW

Дякую. Так, добре, я бачу вашу думку. Але якщо ви регулярно вставляєте цілу країну відразу, кластерний індекс на (країна, місто) здасться мені громіздким, оскільки вимагає сортування даних. З іншого боку, сортування перед вставкою не буде такою великою проблемою ...
littlegreen

3
Звичайно, у вашому прикладі кращим буде унікальний кластерний індекс на {DepartmentID, EmployeeID}? Чому система створює унікальний індикатор, коли ваше існуюче поле забезпечить унікальність із меншими накладними витратами (ймовірно, чотирибайтовим INT) і може дозволити вам виконати ще кілька запитів лише в індексі?
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.