Зачем использовать предложение INCLUDE при создании индекса?

Во время учебы на экзамене 70-433 я заметил, что вы можете создать индекс покрытия одним из следующих двух способов.

CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)

- ИЛИ -

CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)

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

Ответ 1

Если столбец не находится в WHERE/JOIN/GROUP BY/ORDER BY, но только в списке столбцов в предложении SELECT.

Предложение INCLUDE добавляет данные на самом низком/листовом уровне, а не в дерево индексов. Это делает индекс меньше, потому что он не является частью дерева

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

Еще одна статья MSDN с отработанным примером

Ответ 2

Вы должны использовать INCLUDE для добавления одного или нескольких столбцов к уровню листа некластеризованного индекса, если при этом вы можете "покрыть" ваши запросы.

Представьте, что вам нужно запросить идентификатор сотрудника, идентификатор отдела и фамилию.

SELECT EmployeeID, DepartmentID, LastName
FROM Employee
WHERE DepartmentID = 5

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

Если вы включили это последнее имя в свой индекс:

CREATE NONCLUSTERED INDEX NC_EmpDep 
  ON Employee(EmployeeID, DepartmentID)
  INCLUDE (Lastname)

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

Очевидно, что вы не можете включать каждый столбец в каждый некластеризованный индекс, но если у вас есть запросы, в которых отсутствует только один или два столбца, которые будут "покрыты" (и которые будут использоваться много), это может быть очень полезно ВКЛЮЧИТЬ их в подходящий некластеризованный индекс.

Ответ 3

В этом обсуждении отсутствует важный момент: вопрос заключается не в том, что "не-ключевые столбцы" лучше включать в качестве столбцов индекса или как включенные столбцы.

Вопрос в том, насколько дорого стоит использовать include-механизм для включения столбцов, которые действительно не нужны в индексе? (обычно это не часть предложений, но часто включаемых в выборки). Итак, ваша дилемма всегда:

  • Использовать индекс только для id1, id2... idN или
  • Использовать индекс для id1, id2... idN плюс include col1, col2... colN

Где: id1, id2... idN - это столбцы, которые часто используются в ограничениях, а col1, col2... colN - столбцы, которые часто выбираются, но обычно не используются в ограничениях

(Возможность включить все эти столбцы как часть ключа-индекса всегда просто глупо (если они также не используются в ограничениях), потому что всегда будет стоить дороже, поскольку индекс должен обновляться и сортироваться даже если "ключи" не изменились).

Итак, используйте опцию 1 или 2?

Ответ. Если ваша таблица редко обновляется - в основном, вставлена ​​в/удалена из нее, то относительно недорого использовать включенный механизм для включения некоторых "горячих столбцов" (которые часто используются при выборе, но не часто используются на ограничения), так как вставки/удаления требуют, чтобы индекс обновлялся/сортировался в любом случае, и, таким образом, небольшие дополнительные накладные расходы связаны с сохранением нескольких дополнительных столбцов при обновлении индекса. Накладные расходы - дополнительная память и процессор, используемые для хранения избыточной информации об индексе.

Если столбцы, которые вы считаете добавленными как включенные столбцы, часто обновляются (без обновления индексирующих столбцов) - или - если их так много, что индекс близок к копии вашей таблицы - используйте вариант 1 Я бы предложил! Кроме того, если добавление определенных столбцов include (-ов) оказывается неэффективным, вы можете пропустить идею их добавления:) Убедитесь, что они полезны!

Среднее количество строк на одинаковые значения в ключах (id1, id2... idN) также может иметь значение.

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

Ответ 4

Базовые столбцы индекса сортируются, но включенные столбцы не сортируются. Это экономит ресурсы при поддержании индекса, но при этом позволяет предоставлять данные во включенных столбцах для охвата запроса. Таким образом, если вы хотите охватить запросы, вы можете поместить критерии поиска в поиск строк в отсортированные столбцы индекса, но затем включить "дополнительные", несортированные столбцы с данными без поиска. Это определенно помогает уменьшить количество сортировки и фрагментации в обслуживании индексов.

Ответ 5

Причины, по которым (включая данные на уровне листа индекса), были хорошо объяснены. Причина, по которой вы даете два колебания об этом, заключается в том, что при выполнении запроса, если у вас нет дополнительных столбцов (новая функция в SQL 2005), SQL Server должен перейти в кластерный индекс, чтобы получить дополнительные столбцы который занимает больше времени и добавляет больше нагрузки на службу SQL Server, диски и память (конкретный буферный кеш), так как новые страницы данных загружаются в память, что потенциально выталкивает другие более часто требуемые данные из кеша буфера.

Ответ 6

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

Это позволяет включать такие столбцы в индекс покрытия. Я недавно должен был сделать это, чтобы создать сгенерированный nHibernate запрос, в котором было большое количество столбцов в SELECT, с полезным индексом.

Ответ 7

Существует ограничение на общий размер всех столбцов, включенных в определение индекса. Тем не менее, мне никогда не приходилось создавать широко распространенный индекс. Для меня большим преимуществом является тот факт, что вы можете охватить больше запросов одним индексом, который включает столбцы, поскольку они не должны быть определены в каком-либо конкретном порядке. Подумайте, что это индекс в индексе. Одним из примеров может быть StoreID (где StoreID - низкая селективность, означающая, что каждый магазин связан с большим количеством клиентов), а затем демографические данные клиента (LastName, FirstName, DOB): Если вы просто вставляете эти столбцы в этом порядке (StoreID, LastName, FirstName, DOB), вы можете эффективно искать клиентов, для которых вы знаете StoreID и LastName.

С другой стороны, определение индекса в столбцах StoreID и включая LastName, FirstName, DOB позволило бы вам в сущности сделать два предиката index-index на StoreID и затем искать предикат для любого из включенных столбцов. Это позволит вам охватить все возможные перестановки поиска до тех пор, пока он начинается с StoreID.