Некластеризованный индекс использует ключ в кластеризованный индекс вместо адреса?

В документации для SQL Server 2008 R2 заявляется:

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

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

Может кто-нибудь объяснить, пожалуйста?


person Ondrej Peterka    schedule 24.05.2013    source источник


Ответы (1)


Да, именно так и происходит:

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

SQL Server делает это, потому что использование физического адреса было бы действительно плохим:

  • если происходит разделение страницы, все записи, которые перемещаются на новую страницу, будут обновлены
  • для всех этих записей также необходимо обновить все некластеризованные индексы

и это действительно плохо для производительности.

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

И поскольку ключ кластеризации включен в каждый некластеризованный индекс, очень важно, чтобы это был маленький и узкий ключ - оптимально INT IDENTITY или что-то в этом роде - а не огромная структура; Ключ кластеризации - это наиболее реплицируемая структура данных в SQL Server, и он должен быть как можно меньше.

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

person marc_s    schedule 24.05.2013
comment
Спасибо за подтверждение. Не могли бы вы предоставить информацию, почему это так? Разве не быстрее получить адрес напрямую? Я знаю, что поиск в кластеризованном индексе выполняется быстро, как и получение данных, но почему бы не сэкономить время поиска в кластеризованном индексе и не получить доступ к данным напрямую? Или мне что-то здесь не хватает? - person Ondrej Peterka; 24.05.2013
comment
@OndraPeterka: наличие физического адреса имело бы гораздо больше недостатков, и в случае разделения страницы потребовалось бы гораздо больше усилий. - person marc_s; 24.05.2013