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

12

Я искал использование индексированных представлений для повышения производительности в некоторых из наших наиболее часто используемых представлений.

Однако индексированные представления не поддерживают неуникальные кластерные индексы, что немного противоречит приоритету, установленному остальной частью структуры базы данных.

Например, вот упрощенная версия пары наших таблиц.

-Groups-
Group ID    GroupName

-Users-
UserKey    UserName    FullName     GroupID

Индексы находятся на Groups.GroupID (некластеризованный) и Users.GroupID (кластеризованный). Кластерный ключ находится в GroupID в таблице Users, поскольку чаще всего будет найден диапазон пользователей из определенной группы. Очевидно, у вас будет несколько пользователей на группу, поэтому этот кластерный индекс не является уникальным.

Это оставляет меня немного неуверенным в том, как следовать этому приоритету при индексации моих представлений, таких как этот пример, поскольку у меня не может быть неуникального кластеризованного индекса.

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 :

Почему первый индекс в представлении должен быть CLUSTERED и UNIQUE?

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

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

Текущее расположение позволяет включать формы дерева операторов фиксированной формы в базовое дерево запросов DML, обеспечивая ортогональность, которая также упрощает тестирование. В конечном счете, индексированные представления могут быть улучшены за один день для поддержки неуникальных кластеризованных индексов, но с другой стороны, все возможно при неограниченном времени и безграничных ресурсах (ни одно из них не относится к группе разработчиков SQL Server на момент написания).

Для примера, показывающего, как может получаться сложное построение плана запроса на обновление и как легко могут появляться скрытые ошибки, см. Этот пример ошибки , возникающей с MERGEотфильтрованными индексами (функция, тесно связанная с индексированными представлениями).

Пол Уайт 9
источник
2
Подобная ошибка может возникнуть, если вы попытаетесь обновить индексированное представление, в котором есть GROUP BYпредложение, но не все выражения группировки являются ключами в кластерном индексе. Это действительно с SQL Server 2014.
Quassnoi
4

В SQL Server все ключи индекса должны быть внутренне уникальными. Это необходимо для получения ключей блокировки, которые адресуют ровно одну строку. Это также необходимо для ведения индекса. Представьте себе NCI для столбца, который имеет только одно значение (100% дубликатов). Если строка удалена из таблицы, механизм хранения должен найти соответствующую строку NCI и удалить ее. Если бы все строки NCI были неразличимы, это было бы невозможно.

Итак, вы видите, что CI в представлении должен (внутренне) быть уникальным для работы движка.

Если вы не сделаете индекс уникальным, SQL Server все равно сделает его уникальным внутри. В случае NCI в таблице кучи добавляется закладка строки. В случае неуникального CI это добавляет столбец uniquifier. В случае NCI для таблицы с CI он добавляет любые столбцы ключа CI, которые вы сами еще не указали (это может включать в себя иниксификатор).

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

Обычно для человека совершенно очевидно, какие столбцы можно добавить, чтобы у представления был уникальный набор столбцов для использования в CI. Обычно это столбцы PK или CI одной из базовых таблиц. Если представление имеет GROUP BYобычный индекс для ключей группировки.

USR
источник
2
Я настоятельно рекомендую пересмотреть формулировку этого ответа. Несмотря на то, что он содержит правильное замечание относительно исходного вопроса, может показаться, что он предполагает, что все неуникальные индексы содержат унификаторы, что не так.
Спагеттидба
@ spaghettidba спасибо, я этого не заметил. Надеюсь, теперь лучше.
USR
Извините, пока нет. Вы смешиваете две вещи вместе. Некластеризованные индексы не обязательно должны быть уникальными и не должны быть единообразными внутри: вы недостаточно проясняете этот момент. Все, что вы говорите в своем ответе, относится только к кластерным индексам.
спагеттидба
@spaghettidba NCI всегда уникальны внутри. Они всегда могут вывести все ключи CI как часть плана запроса. См. Pastebin.com/vkGHpCsR Страница данных NCI содержит оба столбца.
USR
Я вижу, откуда ты. Несколько листов могут совместно использовать один и тот же индексный ключ, но ключ кластеризации всегда включается в NCI. Достаточно ли сказать, что они всегда уникальны внутри? Я так не думаю.
Спагеттидба