Чому індексовані перегляди не дозволяють не унікальні кластерні індекси?


12

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

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

Наприклад, ось спрощена версія пари наших таблиць.

-Groups-
Group ID    GroupName

-Users-
UserKey    UserName    FullName     GroupID

Індекси розміщені на Group.GroupID (Некластеризований) та Users.GroupID (Clustered). Кластерний ключ, що знаходиться в групі GroupID, в таблиці користувачів, оскільки найчастіше буде знайдено коло користувачів із певної групи. Очевидно, у вас було б кілька користувачів на групу, тому цей кластерний індекс не унікальний.

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

ConsumableID    ConsumableVariantID AllowThresholdOverwrite FullPath    GroupID ManufacturerID  Type    ModelID
101              29                 1                       0.1.2.4.    4       3               3       2

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

Чому перегляди не дозволяють не унікальні кластерні індекси, коли це роблять звичайні таблиці?


3
Внизу цієї сторінки є дуже коротке пояснення під назвою "Чому перший індекс у представленні повинен бути КЛАСТИРОВАНО та УНІКАЛЬНО?" але це не дуже детально. Мені напевно було б цікаво почути більш детальне пояснення.
Стів Петтіфер

5
Пару коментарів: 1 - Немає причини, по якій ви не можете згрупуватися (GroupID, UserID). Не обмежуйтесь одним стовпцем для ключа. 2 - Я уявляю, що обмеження для перегляду є тому, що це додатковий об'єкт даних, який повинен мати рядки, які легко прив'язуються до індексів NC. Для таблиці, унікальний ключ CI отримує доданий до нього int, але я думаю, що це було б складніше з індексованим видом, оскільки це не є фактичною таблицею, але потрібно ПОВЕРНУТИСЯ фактичну таблицю.
JNK

Відповіді:


22

У цій технічній статті Microsoft наведено таке пояснення :

Чому перший індекс для перегляду повинен бути КЛАСТИРОВАНО і УНІКАЛЬНО?

Він повинен бути УНІКАЛЬНИМ для того, щоб дозволити легкий пошук записів у поданні за ключовим значенням під час обслуговування індексованого перегляду, а також запобігти створенню представлень із дублікатами, для чого потрібна спеціальна логіка для підтримки. Він повинен бути кластеризований, оскільки лише кластерний індекс може забезпечити унікальність і зберігати рядки одночасно.

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

Поточне розташування дозволяє включити фігури дерев оператора технічного обслуговування фіксованої форми в базове дерево запитів DML, надаючи ортогональність, що також спрощує тестування. Зрештою, індексовані погляди можна було б покращити за один день для підтримки не унікальних кластерних індексів, але знову ж таки все можливе за необмеженого часу та безмежних ресурсів (жоден з них не застосовується до команди розробників SQL Server на момент написання).

Для прикладу, що показує, як складна побудова плану запитів оновлення та як легко можуть повзати непомітні помилки, дивіться цей приклад помилки, яка виникає із MERGEта відфільтрованими індексами (функція, яка тісно пов'язана з індексованими видами).


2
Подібна помилка може виникнути, якщо ви спробуєте оновити індексований вигляд, який має GROUP BYзастереження, але не всі вирази групування є ключами в кластерному індексі. Це дійсно з SQL Server 2014.
Quassnoi

4

У SQL Server усі індексні ключі повинні бути внутрішньо унікальними. Це потрібно для отримання ключів блокування, які адресують точно один рядок. Він також необхідний для обслуговування індексу. Уявіть NCI на стовпчику, у якому є лише одне значення (100% дублікатів). Якщо рядок буде видалено з таблиці, двигун зберігання повинен знайти відповідний рядок NCI та видалити її. Якщо всі рядки NCI не відрізняються, це було б неможливо.

Отже, ви бачите, що ІС на виду повинен бути (внутрішньо) унікальним для роботи двигуна.

Якщо не зробити унікальний індекс, SQL Server все одно робить його унікальним всередині. У разі NCI на купі таблиці додає закладку рядків. У разі не унікального CI він додає стовпчик уніфікатора. У випадку, якщо NCI на столі з CI додає будь-які стовпці ключів CI, які ви самі ще не вказали (це може включати уніфікатор).

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

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


2
Я настійно пропоную переглянути формулювання цієї відповіді. Хоча він містить дійсну точку щодо оригінального запитання, може виглядати так, що це дозволяє припустити, що всі не унікальні індекси містять уніфікатори, що не так.
spaghettidba

@spaghettidba дякую, я цього не помітив. Сподіваюся, що зараз краще.
usr

Вибачте, поки що. Ви змішуєте дві речі разом. Некластеризовані індекси не повинні бути унікальними і не є уніфікованими внутрішньо: ви не робите цього пункту достатньо зрозумілим. Все, що ви говорите у своїй відповіді, стосується лише кластерних індексів.
spaghettidba

Національні інтерфейси @spaghettidba завжди унікальні всередині країни. Вони завжди можуть виводити всі клавіші CI як частину плану запитів. Дивіться pastebin.com/vkGHpCsR Сторінка даних NCI містить обидва стовпці.
usr

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