Покрытие индексов, когда дополнительные столбцы однозначно определяются кластеризованным индексом

Предположим, мне нужно обновить 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) неявно "покрывает" характер кластеризованного индекса (просто, индекс - это данные на самом низком уровне)
Другие вопросы по тегам