2009-08-20 3 views
333

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

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

- ИЛИ -

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

ВКЛЮЧИТЬ положение является новым для меня. Почему вы используете его и какие рекомендации вы бы предложили при определении того, следует ли создавать индекс покрытия с или без предложения INCLUDE?

ответ

290

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

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

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

Another MSDN article with a worked example

+4

Итак, это будет метод создания менее дорогой версии закрытого индекса? – JMarsch

+1

@gbn, не могли бы вы объяснить это предложение более подробно и объяснить, почему это означает, что предложение include не полезно для сортировки и т. Д.: «Предложение INCLUDE добавляет данные на самом низком/листовом уровне, а не в индекс Это делает индекс меньше, потому что он не является частью дерева « –

+2

@JMarsch: извините за поздний ответ, но да, это именно то, что есть. – gbn

15

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

176

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

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

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

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

Если вы включили, что фамилия в индексе:

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

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

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

+17

Вы уверены, что используете этот индекс? Почему EmployeeID? Вам нужен только DepartmentID в ключевых столбцах? Вы цитировались здесь как авторитарные: http://stackoverflow.com/q/6187904/27535 – gbn

+3

Ваши объяснения хороши, но на самом деле не совпадают с используемым вариантом использования, который вы начертите. Ключевой столбец (столбцы) должны находиться в файле фильтра или 'JOIN' в запросе, а' INCLUDE 'должны быть данными, которые вы извлекаете, но не сортируете. – JNK

+10

Прежде всего индекс Employee (EmployeeID, DepartmentID) не будет использоваться для фильтрации DepartmentID = 5. Поскольку его порядок не соответствует – AnandPhadke

5

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

+0

, есть ли способ доказать, что на самом деле он использует меньше памяти? это то, чего я ожидал бы, но я получаю некоторые статические об этом на работе – Asken

+0

Учитывая, что вам нужно загрузить страницу из кучи или кластерного индекса в память, а также страницу индекса, что означает, что вы помещаете дубликаты данных в памяти математика становится довольно простой. Что касается способа конкретно измерить его, то нет. – mrdenny

2

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

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

4

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

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

16

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

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

  1. Используйте индекс ID1, ID2 ... IDN одна или
  2. Используйте индекс ID1, ID2 ... IDN плюс включают col1, col2 ... ColN

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

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

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

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

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

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

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

Смежные вопросы