Должны ли кластерные индексы быть уникальными?
Что произойдет, если кластерный индекс не является уникальным? Может ли это привести к плохой производительности, потому что вставленные строки перенаправляются на страницу "переполнения" некоторых видов?
Это "сделано" уникальным и если да, то как? Какой лучший способ сделать его уникальным?
Я спрашиваю, потому что в настоящее время я использую кластерный индекс, чтобы разделить свою таблицу на логические части, но производительность так себе, и недавно я получил совет сделать мои кластерные индексы уникальными. Я хотел бы получить второе мнение по этому поводу.
Спасибо!
5 ответов
Они не должны быть уникальными, но это, безусловно, поощряется.
Я еще не сталкивался со сценарием, в котором я хотел создать CI для неуникального столбца.
Что произойдет, если вы создадите CI для неуникального столбца
Если кластерный индекс не является уникальным индексом, SQL Server делает любые дублирующиеся ключи уникальными, добавляя внутренне сгенерированное значение, называемое уникальным
Это приводит к плохой производительности?
Добавление уникализатора, безусловно, увеличивает накладные расходы при его вычислении и хранении.
Если эти накладные расходы будут заметны, зависит от нескольких факторов.
- Сколько данных содержит таблица.
- Какова скорость вставок.
- Как часто CI используется в выборе (когда индексы покрытия не существуют, почти всегда).
редактировать
Как было отмечено Ремусом в комментариях, существуют случаи использования, когда создание неуникального КИ было бы разумным выбором. То, что я не столкнулся с одним из этих сценариев, просто показывает, что у меня недостаточно внимания или компетенции (выберите свой выбор).
Мне нравится проверять, что говорит по этому поводу королева индексации Кимберли Трипп:
Я собираюсь начать с моей рекомендации по ключу кластеризации - по нескольким причинам. Во-первых, это простое решение, а во-вторых, принятие этого решения на раннем этапе помогает упреждающе предотвратить некоторые виды фрагментации. Если вы можете предотвратить определенные типы фрагментации базовых таблиц, вы можете минимизировать некоторые операции обслуживания (некоторые из которых в SQL Server 2000 и менее в SQL Server 2005) требуют, чтобы ваша таблица была в автономном режиме. Хорошо, я вернусь к перестройке позже...
Давайте начнем с ключевых вещей, которые я ищу в ключе кластеризации:
* Unique
* Narrow
* Static
Почему уникальный? Ключ кластеризации должен быть уникальным, поскольку ключ кластеризации (если таковой существует) используется в качестве ключа поиска для всех некластеризованных индексов. Возьмем, к примеру, индекс в конце книги - если вам нужно найти данные, на которые указывает запись в индексе - эта запись (запись в индексе) должна быть уникальной, в противном случае эта запись индекса будет той, которую вы ищете? Итак, когда вы создаете кластерный индекс - он должен быть уникальным. Но SQL Server не требует, чтобы ваш ключ кластеризации создавался в уникальном столбце. Вы можете создать его в любом столбце (столбцах), который хотите. Внутренне, если ключ кластеризации не является уникальным, SQL Server "унифицирует" его, добавляя к данным 4-байтовое целое число. Таким образом, если кластерный индекс создается для чего-то, что не является уникальным, то не только возникают дополнительные издержки при создании индекса, тратится впустую дисковое пространство, дополнительные затраты на INSERT и UPDATE, а в SQL Server 2000 добавляется стоимость для индекса clusterteD. перестроить (что из-за плохого выбора ключа кластеризации теперь более вероятно).
Источник: постоянно растущие ключевые дискуссии о кластеризации - снова!
Должны ли кластерные индексы быть уникальными?
Они не делают, и бывают времена, когда лучше, если они не.
Рассмотрим таблицу с полуслучайным, уникальным EmployeeId и DepartmentId для каждого сотрудника: если ваш оператор выбора
SELECT * FROM EmployeeTable WHERE DepartmentId=%DepartmentValue%
тогда это лучше для производительности, если DepartmentId
является кластеризованным индексом, даже если (или даже особенно потому, что) он не является уникальным индексом (лучше всего подходит для производительности, поскольку он обеспечивает кластеризацию всех записей в данном DepartmentId).
У вас есть какие-либо ссылки?
Например, есть рекомендации по проектированию кластерного индекса, в которых говорится:
За некоторыми исключениями, каждая таблица должна иметь кластерный индекс, определенный для столбца или столбцов, которые предлагают следующее:
- Может использоваться для часто используемых запросов.
- Обеспечить высокую степень уникальности.
- Может использоваться в запросах диапазона.
Например, мое понимание "высокой степени уникальности" заключается в том, что нехорошо выбирать "Страна" в качестве кластерного индекса, если большинство ваших запросов хотят выбрать записи в данном городе.
Если вы настраиваете старую БД, это находка. Я работаю над проблемами Perf в базе данных 20-летней давности. Он имеет некластеризованные ПК с 3–8 столбцами. Вместо того, чтобы использовать все 8 столбцов, чтобы быть уникальными, я могу выбрать один столбец с широким распределением, и он применит Uniqueifier. Это тип Int, но с помощью столбца, такого как идентификатор проекта, он может обрабатывать 2 147483647 уникальных идентификаторов проекта, чего достаточно для большинства случаев использования. Если этого недостаточно, добавьте в кластер второй или третий столбец. Это работает без каких-либо изменений кода на уровне приложения. 20 лет в производстве и управлении не требуют серьезных изменений.
На вопрос «Должны ли кластеризованные индексы быть уникальными?» Нет! Подумайте об этой ситуации: у вас 100 записей. Вам нужны записи с идентификатором = 50–59 (значения идентификатора). Кластерный индекс сканирует записи, пока не найдет идентификатор = 50. Он собирает записи, пока не достигнет идентификатора = 60, и останавливается (кластеризованный индекс знает после 59 записей больше не будет) Таким образом, кластеризацию можно рассматривать как частный случай ORDER BY
СЕЙЧАС Если в вашей таблице есть столбец ID, чтобы сделать записи уникальными, и UID для того, кто вставляет запись, вы можете кластеризовать ее по UID, чтобы внешний интерфейс мог запрашивать записи по UID, в то время как PK является идентификатором. Этот случай зависит от того, как вы собираетесь использовать данные.