Покрытие индексов, когда дополнительные столбцы однозначно определяются кластеризованным индексом
Предположим, мне нужно обновить myTab из luTab следующим образом
update myTab
set LookupVale = (select LookupValue from luTab B
where B.idLookup = myTab.idLookup)
luTab состоит из 2 столбцов (idLookup(уникальный), LookupValue)
Что предпочтительнее: уникальный кластеризованный индекс для idLookup или индекс для idLookup и Lookupvalue вместе взятые? Будет ли индекс покрытия иметь какое-либо значение в этой ситуации?
(Меня больше всего интересует SQL-сервер)
Эпилог:
Ниже я проверил тесты Krips с 27 миллионами строк в myTab, 1,5 миллионами строк в luTab. Важнейшей частью, кажется, является уникальность индекса. Если индекс указан как уникальный, обновление использует хеш-таблицу. Если он не указан как уникальный, то обновление сначала агрегирует luTab с помощью idLookup (Stream Aggegate), а затем использует вложенный цикл. Это намного медленнее. Когда я использую расширенный индекс, SQL больше не предполагает, что это LookupValue является уникальным, поэтому он вынужден идти по гораздо более медленному, циклически объединенному маршруту потока
2 ответа
Я создал ваши таблицы и загрузил всего несколько записей (около 50 поисков и 15 в myTab).
Затем я попробовал различные варианты индекса. Поиск индекса на luTab всегда имеет стоимость 29%.
Интересным моментом является то, что если вы добавите столбец LookupValue к индексу на luTab, план выполнения покажет два дополнительных шага после поиска индекса: агрегирование потока и утверждение. Хотя стоимость составляет 0%, это может привести к увеличению объема данных.
Я также попробовал некластеризованный индекс только для idLookup и включил LookupValue в качестве "включенного столбца". Таким образом, нет необходимости обращаться к страницам данных, чтобы получить этот столбец. Это может быть вариант для вас, хотя план выполнения не показывает ничего другого (но они также не имеют Агрегат / Утверждение потока).
-Krip
Во-первых:
- Индекс покрытия всегда некластеризован
- У вас всегда должен быть PK и кластеризованный индекс (по умолчанию они одинаковы для SQL Server)
2 понятия являются отдельными
Так:
- Ваш PK (кластеризованный) будет idLookup, если это однозначно идентифицирует строку
- Индекс покрытия будет (idLookup) INCLUDE (LookupValue)
Тем не мение:
- idLookup - это PK (кластеризованный), поэтому вам не нужен индекс покрытия
- кластеризованный индекс (PK) неявно "покрывает" характер кластеризованного индекса (просто, индекс - это данные на самом низком уровне)