Зачем использовать предложение INCLUDE при создании индекса? - PullRequest
403 голосов
/ 20 августа 2009

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

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

- ИЛИ -

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

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

Ответы [ 8 ]

341 голосов
/ 20 августа 2009

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

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

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

Другая статья MSDN с работающим примером

208 голосов
/ 20 августа 2009

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

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

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

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

Если вы включили эту фамилию в свой индекс:

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

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

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

25 голосов
/ 13 июня 2015

В этом обсуждении упущен важный момент: вопрос не в том, лучше ли включать «не ключевые столбцы» в виде index -колонок или в качестве включенных - столбцы.

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

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

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

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

Так используйте вариант 1 или 2?

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

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

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

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

17 голосов
/ 20 августа 2009

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

6 голосов
/ 22 августа 2009

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

5 голосов
/ 21 октября 2013

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

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

2 голосов
/ 01 марта 2011

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

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

1 голос
/ 30 мая 2019

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

Учитывая ваш пример:

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

Этот индекс лучше всего подходит, если ваш запрос выглядит следующим образом:

SELECT col2, col3
  FROM MyTable
 WHERE col1 = ...

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

SELECT col2, col3
  FROM MyTable
 WHERE col1 = ...
   AND col2 = ...
SELECT TOP 1 col2, col3
  FROM MyTable
 WHERE col1 = ...
 ORDER BY col2

Давайте предположим, что это , а не , и у нас есть col2 в предложении INCLUDE, потому что его просто нет в древовидной части индекса.

Перемотка вперед на несколько лет.

Вам нужно настроить этот запрос:

SELECT TOP 1 col2
  FROM MyTable
 WHERE col1 = ...
 ORDER BY another_col

Для оптимизации этого запроса будет полезен следующий индекс:

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

Если вы проверите, какие индексы у вас уже есть в этой таблице, ваш предыдущий индекс все еще может быть там:

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

Теперь вы знаете, что Col2 и Col3 не являются частью дерева индексов и, таким образом, не используются для сужения диапазона индекса чтения и для упорядочения строк. Довольно безопасно добавить another_column в конец ключевой части индекса (после col1). Существует небольшой риск что-либо сломать:

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

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

Если бы у вас был индекс без INCLUDE, вы не могли бы знать, какие запросы вы бы разбили, добавив another_col сразу после Col1.

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

Что произойдет, если вы добавите another_col между Col1 и Col2? Будут ли страдать другие запросы?

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

Чтобы ответить на ваш вопрос:

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

Если вы добавляете столбец в индекс с единственной целью, чтобы этот столбец был доступен в индексе без посещения таблицы, поместите его в предложение INCLUDE.

Если добавление столбца к ключу индекса приносит дополнительные преимущества (например, для order by или потому, что это может сузить диапазон индекса чтения), добавьте его к ключу.

Более подробное обсуждение можно прочитать здесь:

https://use -the-index-luke.com / блог / 2019-04 / include-колонки-в-ВТКЕЕ-индексы

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...