Это превращается в более общее введение в индексирование, но я подозреваю, что вы все равно найдете его полезным. Первые два абзаца особенно касаются вашего вопроса.
Кластеризованные и некластеризованные
Это относится к физическому расположению таблицы на диске. Кластерный индекс работает путем сортировки физических страниц и строк в таблице на диске на основе определения индекса. Некластеризованные индексы используют отдельное расположение на диске для хранения копии столбцов в индексе (и только этих столбцов), а также указателя на исходные записи. По этой причине кластерные индексы часто работают быстрее, потому что они всегда будут покрывать любые данные, которые вам нужны в запросе. Однако вы получаете только один из них, потому что в противном случае вы дублируете всю таблицу. Также важно знать, что добавление некластеризованных индексов в таблицу на самом деле замедляет операции записи, такие как вставки и обновления, потому что база данных должна перестраивать индекс или, по крайней мере, определенные страницы в индексе.
Индекс заказа
Индекс для (A,B)
равен , а не такой же, как для (B,A)
. Если в первом случае записи в индексе упорядочены сначала по столбцу A
, а столбец B
влияет только на порядок индекса, если у вас есть повторяющиеся значения для A
. Поиск по индексу только со значением столбца B
не поможет вам, потому что вам все равно нужно просмотреть каждую запись в индексе, чтобы найти все совпадающие значения в B
. Во втором случае происходит обратное: записи упорядочиваются сначала по столбцу B
, а столбец A
помогает только при наличии повторяющихся значений для A
. Поиск по этому индексу только по столбцу A
не поможет.
Индексы покрытия
Иногда база данных может полностью выполнить требования запроса из индекса. В этом случае говорят, что индекс является «покрывающим» индексом для этого запроса. Это выгодно, потому что индексы часто кэшируются в памяти, и поэтому базе данных, возможно, вообще не нужно делать диск. Чтобы понять это, представьте индекс на (A,B)
, где очень мало повторяющихся значений для A
. Включение A
в индекс кажется расточительным, если только у вас нет часто выполняющегося запроса, который ищет определенное значение A
и также нуждается в B
. Этот индекс теперь сохранит много работы, возвращаясь к исходной таблице для получения B
.
Избирательность
Селективность - это значение от 0 до 1 (часто выражается в процентах), которое указывает, насколько уникальным является каждое значение в индексе. Селективность 1 или 100% означает, что дубликатов нет. Селективность 0 означает, что в столбце есть только одно значение. Как правило, более высокая селективность (приближающаяся к 1) лучше для индексов.
Чтобы продемонстрировать это, подумайте о том, что произойдет с индексом низкой селективности. Например, вы пытаетесь ускорить запрос, добавив индекс к битовому столбцу в таблице с 10000 записями. В этом случае (при условии равномерного распределения) селективность составляет .5. Вы выполняете запрос, и индекс возвращает 5000 записей. Но каждая из этих записей по-прежнему должна возвращаться к исходной таблице, и, поскольку порядок индекса не совпадает с порядком таблицы, необходимо выполнить множество отдельных проверок в таблице. Вместо этого, скорее всего, быстрее просто просмотреть всю таблицу от начала до конца, чтобы получить необходимые данные.
Избирательность объясняет, почему вы хотите кластеризоваться на первичном ключе. Так как кластеризованный индекс сообщает базе данных, как упорядочить таблицу, выбор степени ниже 100% означает, что запрос должен будет сканировать таблицу чаще. Кластеризация по первичному ключу обеспечивает идеальную избирательность. А поскольку этот первичный ключ часто используется в качестве указателя записи в других индексах, вы хотите, чтобы он был как можно меньше (т. Е. Столбец целочисленных идентификаторов).
Здесь есть хорошая статья о селективности и индексации:
http://www.akadia.com/services/ora_index_selectivity.html
Sargable
Это относится к тому, может ли база данных использовать определенный фильтр с индексом.
Как мы показали, индексы обычно работают, сначала сортируя данные в определенном порядке, так что при поиске в этом индексе можно использовать что-то эффективное, например, поиск по дереву, а не более медленный линейный поиск. Все, что нельзя эффективно сравнить с отсортированными данными, нельзя использовать с индексом. Хорошим примером является оператор LIKE
. Это прощается:
SELECT * FROM [Table] WHERE [Column] LIKE @Value + '%'
но это не sargable:
SELECT * FROM [Table] WHERE [Column] LIKE '%' + @Value + '%'
Некоторые другие вещи, которые могут сделать фильтр невозможным, - это недетерминированные функции (а их больше, чем вы думаете).
Индексы по столбцам
Распространенная ошибка, которую я видел, - иметь отдельный индекс для каждого столбца в таблице. Например, кто-то возьмет таблицу со столбцами (A,B,C,D)
и создаст четыре отдельных индекса, по одному для A
, B
, C
, D
, полагая, что они теперь проиндексировали каждый столбец, и поэтому каждый запрос должен быть быстрым. На самом деле, это редко бывает полезно по причинам, которые, я надеюсь, я уже объяснил, и часто будет усугублять, а не улучшать, потому что базе данных теперь нужно будет обновлять эти индексы для каждого изменения данных.