Во время подготовки к экзамену 70-433 я заметил, что вы можете создать индекс покрытия одним из следующих двух способов.
CREATE INDEX idx1 ON MyTable (Col1, Col2, Col3)
-- ИЛИ --
CREATE INDEX idx1 ON MyTable (Col1) INCLUDE (Col2, Col3)
Предложение INCLUDE является новым для меня. Зачем вам его использовать и какие рекомендации вы бы предложили при определении, создавать ли индекс покрытия с предложением INCLUDE или без него?
SELECT
а для некоторых нет? \Вы бы использовали INCLUDE, чтобы добавить один или несколько столбцов к конечному уровню некластеризованного индекса, если, сделав это, вы можете «покрыть» ваши запросы.
Представьте, что вам нужно запросить идентификатор сотрудника, идентификатор отдела и фамилию.
Если у вас есть некластеризованный индекс (EmployeeID, DepartmentID), как только вы найдете сотрудников для определенного отдела, вам теперь нужно выполнить «поиск по закладкам», чтобы получить фактическую полную запись о сотруднике, просто чтобы получить столбец фамилии , Это может быть довольно дорого с точки зрения производительности, если вы найдете много сотрудников.
Если вы включили эту фамилию в свой индекс:
тогда вся необходимая информация доступна на уровне листьев некластеризованного индекса. Просто просматривая некластеризованный индекс и находя ваших сотрудников для данного отдела, вы получаете всю необходимую информацию, и поиск закладок для каждого сотрудника, найденного в индексе, больше не требуется -> вы экономите много времени.
Очевидно, что вы не можете включить каждый столбец в каждый некластеризованный индекс - но если у вас есть запросы, в которых отсутствует только один или два столбца, которые нужно «покрыть» (и которые часто используются), это может быть очень полезно, чтобы ВКЛЮЧИТЬ эти в подходящий некластерный индекс.
источник
JOIN
ключах в запросе, а столбцы должны бытьINCLUDE
данными, которые вы извлекаете, но не сортируете.В этом обсуждении упущен важный момент: вопрос не в том, лучше ли включать «не ключевые столбцы» в качестве столбцов индекса или включенных столбцов.
Вопрос в том, насколько дорого использовать механизм включения для включения столбцов, которые на самом деле не нужны в индексе ? (обычно не входит в предложения where, но часто включается в выборки). Так что ваша дилемма всегда:
Где: id1, id2 ... idN - столбцы, часто используемые в ограничениях, а col1, col2 ... colN - часто выбираемые столбцы, но обычно они не используются в ограничениях.
(Возможность включить все эти столбцы как часть ключа индекса всегда глупа (если только они не используются в ограничениях) - поддерживать его всегда будет дороже, так как индекс должен обновляться и сортироваться, даже если «ключи» не изменились).
Так использовать вариант 1 или 2?
Ответ: Если ваша таблица редко обновляется - в основном вставляется / удаляется из - тогда использовать механизм включения для включения некоторых «горячих столбцов» относительно недорого (которые часто используются в выборках - но не часто используются в ограничениях), поскольку вставки / удаления требуют, чтобы индекс все равно обновлялся / сортировался, и, таким образом, небольшая дополнительная нагрузка связана с сохранением нескольких дополнительных столбцов при уже обновлении индекса. Накладные расходы - это дополнительная память и процессор, используемые для хранения избыточной информации в индексе.
Если столбцы, которые вы хотите добавить как включенные столбцы, часто обновляются (без обновления ключа ключа индекса) - или - если их так много, что индекс становится близким к копии вашей таблицы - используйте опцию 1 Я бы предложил! Кроме того, если добавление определенных столбцов include-столбцов не оказывает никакого влияния на производительность - вы можете пропустить идею их добавления :) Убедитесь, что они полезны!
Среднее число строк на одно и то же значение в ключах (id1, id2 ... idN) также может иметь некоторое значение.
Обратите внимание , что если столбец - который добавляется как включен -column индекса - используется в ограничении : До тех пор , как индекс , как таковой , может быть использован ( на основе ограничений в отношении index- ключевых -columns) - то SQL - сервер является соответствие ограничение столбца по отношению к индексу (leaf-node-values) вместо дорогостоящего обхода самой таблицы.
источник
Столбцы основного индекса сортируются, но включенные столбцы не сортируются. Это экономит ресурсы на поддержание индекса, в то же время позволяя предоставлять данные во включенных столбцах для покрытия запроса. Итак, если вы хотите охватить запросы, вы можете поместить критерии поиска, чтобы найти строки в отсортированных столбцах индекса, но затем «включить» дополнительные несортированные столбцы с данными, не относящимися к поиску. Это определенно помогает уменьшить количество сортировки и фрагментации в обслуживании индекса.
источник
Причины (включая данные на уровне листа индекса) были хорошо объяснены. Причиной, по которой вы получаете два эффекта, является то, что при выполнении запроса, если у вас нет дополнительных столбцов (новая функция в SQL 2005), SQL Server должен перейти к кластерному индексу, чтобы получить дополнительные столбцы Это занимает больше времени и увеличивает нагрузку на службу SQL Server, диски и память (в частности, буферный кэш), так как новые страницы данных загружаются в память, что потенциально выталкивает другие более часто необходимые данные из буферного кеша.
источник
Дополнительное соображение, которое я не видел в уже приведенных ответах, заключается в том, что включенные столбцы могут относиться к типам данных, которые не допускаются в качестве столбцов ключа индекса, например varchar (max).
Это позволяет включать такие столбцы в индекс покрытия. Недавно мне пришлось сделать это, чтобы предоставить сгенерированный запрос nHibernate, в котором было много столбцов в SELECT, с полезным индексом.
источник
Одной из причин отдавать предпочтение
INCLUDE
ключевым столбцам, если вам не нужен этот столбец в ключе, является документация. Это делает развивающиеся индексы намного более легкими в будущем.Учитывая ваш пример:
Этот индекс лучше всего подходит, если ваш запрос выглядит так:
Конечно, вы не должны вставлять столбцы,
INCLUDE
если вы можете получить дополнительную выгоду от их наличия в ключевой части. Оба следующих запроса фактически предпочитаютcol2
столбец в ключе индекса.Давайте предположим, что это не так, и мы имеем
col2
вINCLUDE
предложении, потому что нет никакой выгоды иметь его в древовидной части индекса.Перемотка вперед на несколько лет.
Вам нужно настроить этот запрос:
Чтобы оптимизировать этот запрос, подойдет следующий индекс:
Если вы проверите, какие индексы у вас уже есть в этой таблице, ваш предыдущий индекс все еще может быть там:
Теперь вы знаете , что
Col2
иCol3
не являются частью индексного дерева и, таким образом , не используются , чтобы сузить диапазон индексов для чтения , ни для упорядочения строк. Достаточно безопасно добавитьanother_column
в конец ключевой части индекса (послеcol1
). Существует небольшой риск сломать что-либо:Этот индекс станет больше, что по-прежнему сопряжено с некоторыми рисками, но, как правило, лучше расширять существующие индексы, чем вводить новые.
Если бы у вас был индекс без
INCLUDE
, вы не могли бы знать, какие запросы вы нарушите, добавивanother_col
сразу послеCol1
.Что произойдет, если вы добавите
another_col
междуCol1
иCol2
? Будут ли страдать другие запросы?Существуют и другие «преимущества»
INCLUDE
столбцов против ключа, если вы добавляете эти столбцы просто для того, чтобы избежать их извлечения из таблицы . Тем не менее, я считаю аспект документации самым важным.Чтобы ответить на ваш вопрос:
Если вы добавляете столбец в индекс с единственной целью, чтобы этот столбец был доступен в индексе без посещения таблицы, поместите его в
INCLUDE
предложение.Если добавление столбца к ключу индекса приносит дополнительные преимущества (например, для
order by
или потому, что оно может сузить диапазон индекса чтения), добавьте его к ключу.Вы можете прочитать более подробное обсуждение этого здесь:
https://use-the-index-luke.com/blog/2019-04/include-columns-in-btree-indexes
источник
Существует ограничение на общий размер всех столбцов, встроенных в определение индекса. Тем не менее, мне никогда не приходилось создавать такой широкий индекс. Для меня большее преимущество заключается в том, что вы можете охватить больше запросов одним индексом, который включает столбцы, поскольку их не нужно определять в каком-то определенном порядке. Думайте о том, как индекс в индексе. Одним из примеров может быть StoreID (где StoreID - низкая селективность, что означает, что каждый магазин связан с большим количеством клиентов), а затем демографические данные клиентов (LastName, FirstName, DOB): если вы просто вставляете эти столбцы в этом порядке (StoreID, LastName , FirstName, DOB), вы можете эффективно искать только тех клиентов, для которых вы знаете StoreID и LastName.
С другой стороны, определение индекса для StoreID и включение столбцов LastName, FirstName, DOB, по сути, позволит вам выполнить два предиката индекса поиска для StoreID, а затем искать предикат для любого из включенных столбцов. Это позволит вам охватить все возможные варианты поиска, если он начинается с StoreID.
источник