Индексы с включенными столбцами, в чем разница?
Я никогда не понимал разницу между этими двумя индексами, может кто-нибудь объяснить, в чем разница (производительность, как будет выглядеть структура индекса в БД, хранилище и т. д.)?
Я понимаю, что этот вопрос является широкий, пожалуйста, медведь со мной. Я действительно не знаю, как это сделать. Возможно, если вы, ребята, начнете объяснять свои ноу-хау, я получу указатели в правильном направлении, что позволит мне сделать вопрос больше узкий?
включил указатель
CREATE NONCLUSTERED INDEX IX_Address_PostalCode
ON Person.Address (PostalCode)
INCLUDE (AddressLine1, AddressLine2, City, StateProvinceID);
"нормальный" показатель
CREATE NONCLUSTERED INDEX IX_Address_PostalCode
ON Person.Address (PostalCode, AddressLine1, AddressLine2, City, StateProvinceID);
3 ответов
внутреннее хранилище индексов использует структуру B-дерева и состоит из "индексных страниц" (корневых и всех промежуточных страниц) и "индексных страниц данных" (только листовые страницы).
Примечание не путайте "страницы данных индекса" с "страницами данных" (листовыми страницами кластеризованных индексов), которые хранят большую часть столбцов фактических данных.
- на страницах индекса хранятся только столбцы индекса.
- путем устанавливать некоторые столбцы в
INCLUDE
раздел, меньше данных на ключ индекса хранится на каждой странице. - означает, что для хранения ключей индекса требуется меньше страниц. (что упрощает кэширование этих часто используемых страниц в памяти дольше.)
- и, возможно, меньше уровней в дереве. (в таком случае преимущества производительности могут быть намного больше, потому что каждый обход уровня дерева-это другой доступ к диску.)
при использовании индекса используется ключ индекса чтобы перейти по страницам индекса к правильной странице данных индекса.
- событие
INCLUDE
столбцы, эти данные немедленно доступны, если запрос нуждается в этом. - если запрос требует столбцов, недоступных ни в ключах индекса, ни в
INCLUDE
столбцы, затем требуется дополнительный "поиск закладок" для правильной строки в кластеризованном индексе (или кучи, если кластеризованный индекс не определен).
некоторые вещи, чтобы отметить, что мы надеемся адресует некоторые из вашей путаницы:
- если ключи вашего индекса и фильтров в вашем запросе не выборочная достаточно, тогда индекс будет проигнорирован (независимо от того, что в вашем
INCLUDE
столбцы). - каждый индекс, который вы создаете, имеет накладные расходы для инструкций INSERT и UPDATE; тем более для "больших" индексов. (Больше относится к
INCLUDE
колонки, а также.) - таким образом, в то время как вы могли бы теоретически создать множество больших индексов с include столбцы, соответствующие всем перестановкам путей доступа: это было бы очень контрпродуктивно.
стоит отметить, что до INCLUDE
столбцы были добавлены в качестве объекта:
- это был обычный "трюк" настройки индекса, чтобы расширить ключи индекса, чтобы включить столбцы, которые не были нужны в индексе/фильтре. (Известен как индекс покрытия.)
- эти столбцы обычно требуются в выходных столбцах или в качестве ссылочных столбцов для соединений с другие столики.
- это позволило бы избежать печально известных "поисков закладок", но имело недостаток в том, что индекс "шире", чем это необходимо.
- на самом деле очень часто более ранние столбцы в индексе уже идентифицировали бы строку означает, что дополнительные включенные столбцы были бы полностью избыточными, если бы не преимущество "избежать поиска закладок".
-
INCLUDE
столбцы в основном позволяют ту же выгоду больше эффективно.
NB что-то очень важное, чтобы указать. Вы обычно получаете нулевую выгоду от
INCLUDE
столбцы в индексах, если у вас есть ленивая привычка всегда писать свои запросы какSELECT * ...
. По возвращении все столбцы вы в основном гарантируете, что поиск закладок требуется в любом случае.
в первом индексе, в Index page
только PostalCode
является ключевым столбцом и AddressLine1, AddressLine2, City, StateProvinceID
являются частью листового узла, чтобы избежать key/RID
поиск
Я предпочитаю первый индекс, когда моя таблица будет фильтроваться всегда на PostalCode
и любой из этих столбцов AddressLine1, AddressLine2, City, StateProvinceID
будет частью select
и не фильтрации
select AddressLine1, AddressLine2, City, StateProvinceID
from Person.Address
Where PostalCode=
во втором индексе, в Index page
будет пять ключевых столбцов PostalCode, AddressLine1, AddressLine2, City, StateProvinceID
Я предпочитаю второй показатель, когда у меня есть возможность фильтровать данные как
Where PostalCode = And AddressLine1 =
или
Where PostalCode = And AddressLine2 =
или
Where PostalCode = And AddressLine1 = and AddressLine2 =
и так далее..
в любом случае первый столбец в индексе должен быть частью фильтрации, чтобы использовать индекс
в первом примере только столбец индекса: PostalCode хранится в дереве индекса со всеми другими столбцами, хранящимися на уровне листа индекса. Это делает индекс меньше по размеру и полезно, если вы не используете where, Join, group by против других столбцов, но только против PostalCode.
во втором индексе все данные для всех столбцов хранятся в дереве индексов, что делает индекс намного больше, но полезно, если вы будете использовать любой из столбцы в операторах WHERE/JOIN/GROUP BY/ORDER By.
включить столбцы позволяет быстрее извлекать данные, когда они указаны в списке выбора.
например, если вы работаете:
SELECT PostalCode, AddressLine1, AddressLine2, City, StateProvinceID
FROM Person.Address
Where PostalCode= 'A1234'
это выиграет от создания индекса на PostalCode и включая все другие столбцы
С другой стороны, если вы работаете:
SELECT PostalCode, AddressLine1, AddressLine2, City, StateProvinceID
FROM Person.Address
Where PostalCode= 'A1234' or City = 'London' or StateProvinceID = 1 or AddressLine1 = 'street A' or AddressLine2 = 'StreetB'
Это выиграло бы больше от наличия всех столбцов в индекс
посмотрите на ссылки ниже, это может помочь больше с вашим запросом
индекс с включенным столбцом:https://msdn.microsoft.com/en-us/library/ms190806 (v=sql.105).aspx
организация таблицы и индекса:https://msdn.microsoft.com/en-us/library/ms189051 (v=sql.105).aspx