Почему использование ВКЛЮЧАЕТ в индекс SQL

Я недавно встретился с индексом в базе данных, я поддерживаю, что имел форму:

CREATE INDEX [IX_Foo] ON [Foo]
( Id ASC )
INCLUDE 
( SubId )

В данном случае проблема производительности, с которой я встречался (медленная фильтрация ВЫБОРА и на идентификаторе и на SubId) могла быть решена путем простого перемещения столбца SubId в надлежащий индекс, а не как включенный столбец.

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

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

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

Я считаю прохождение через других индексов в базе данных и смещении включенных столбцов в индексе надлежащим, если это возможно. Это было бы ошибкой?

Я, прежде всего, интересуюсь SQL Server MS, но информация о других механизмах DB приветствуется также.

14
задан mjv 13 March 2010 в 01:50
поделиться

3 ответа

Пока все ответы верны и все такое, но они могут не передать достаточно того, что вы получаете от покрывающего индекса.

В вашем случае у вас есть таблица Foo и некоторые поля, включая Id (который, как я предполагаю, является первичным ключом), и SubId это какой-то дополнительный идентификатор.

У вас также есть индекс IX_Foo , который, как я полагаю, пока содержал только Id .

Итак, теперь вам нужно найти SubId для Id = 4 .

SELECT Id, SubId
FROM Foo
WHERE Id=4
  • SQL Server просмотрит инструкцию SELECT и определит, что он может использовать IX_Foo
  • , а затем перейдет к поиску значения Id = 4 в вашем индексе IX_Foo
  • когда он его находит, ему теперь требуется значение SubId , также
  • некластеризованный индекс IX_Foo будет содержать значение ключа кластеризации
  • с использованием этого значения ключа кластеризации, SQL Server выполнит «поиск по закладкам», чтобы найти фактическую страницу данных, на которой находится вся ваша строка данных
  • , он извлечет эту страницу и извлечет из нее значение для SubId
  • он вернет эти значения, чтобы удовлетворить ваш запрос

Главное здесь: как только SQL Server обнаружит ваш Id = 4 в индексе IX_Foo , ему потребуется выполнить еще один ввод / Операция O, поиск по закладке, чтобы получить всю строку данных, чтобы можно было найти значение SubId .

Если у вас есть индекс покрытия, например IX_Foo также включает SubId , что исключает дополнительный ввод-вывод для поиска закладок.Как только значение Id = 4 будет найдено в индексе IX_Foo , эта страница индекса в вашем некластеризованном индексе также будет включать значение SubId - SQL Server теперь может возвращать те два значения, которые вы запрашивали в запросе SELECT , без необходимости выполнения дополнительного (потенциально дорогостоящего и, следовательно, медленного) поиска по закладкам только для того, чтобы получить другой столбец Id.

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

ОБНОВЛЕНИЕ: компромисс заключается в следующем: если у вас есть индекс на (Id, SubId), все страницы в индексе имеют оба столбца - все дерево индекса.

Если вы ВКЛЮЧИТЕ (SubId), поля SubId будут присутствовать только на конечном уровне.

Это означает, что

  • SQL Server не может выполнять поиск и сравнение по SubId (значения отсутствуют в индексном дереве)
  • используется меньше места, поскольку значения находятся только на конечном уровне
8
ответ дан 1 December 2019 в 13:33
поделиться

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

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

7
ответ дан 1 December 2019 в 13:33
поделиться

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

3
ответ дан 1 December 2019 в 13:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: