Каковы последствия преобразования индексов кучи в кластеризованные индексы на SQL Server?

Недавно я получил совет, что я должен преобразовать все наши таблицы с использованием индексов кучи, чтобы каждая таблица имела кластерный индекс. Каковы последствия убеждения в этой стратегии? Например. важнее регулярно реорганизовывать базу данных? рост данных? опасность действительно медленных вставок? Опасность дефрагментации страницы, если PK является GUID? Заметно увеличилась скорость работы моего приложения? Каковы ваши впечатления?

Чтобы послужить источником вдохновения для хороших ответов, вот некоторые из «фактов», которые я почерпнул из других потоков здесь, в stackoverflow.

  1. Почти наверняка захочется установить кластерный индекс для каждой таблицы в вашей базе данных. Если в таблице его нет. Производительность наиболее распространенных запросов лучше.
  2. Кластерные индексы не всегда плохо работают с идентификаторами GUID ... все зависит от потребностей вашего приложения. Скорость INSERT пострадает, но скорость SELECT будет улучшена.
  3. Проблема с кластеризованными индексами в поле GUID заключается в том, что идентификаторы GUID являются случайными, поэтому при вставке новой записи значительную часть данных на диске необходимо переместить, чтобы вставить записи в середину таблицы.
  4. Кластерный индекс по GUID подходит в ситуациях, когда GUID имеет значение и повышает производительность за счет размещения связанных данных близко друг к другу http://randommadness.blogspot.com/2008/07/guids-and-clustered-indexes.html
  5. Кластеризация не влияет на скорость поиска - уникальный некластеризованный индекс должен выполнять свою работу.

person Carlo V. Dango    schedule 13.12.2010    source источник


Ответы (3)


Если ваш ключ - это GUID, то некластеризованный индекс на нем, вероятно, так же эффективен, как и кластеризованный индекс на нем. Это потому, что на GUID вы никогда не сможете сканировать диапазон (что может означать between 'b4e8e994-c315-49c5-bbc1-f0e1b000ad7c' and '3cd22676-dffe-4152-9aef-54a6a18d32ac' ??). При ширине 16 байт ключ кластеризованного индекса GUID шире, чем идентификатор строки, который вы получили бы из кучи, поэтому NC-индекс в руководстве PK на самом деле является стратегией, которую можно защитить в ходе обсуждения.

Но превращение первичного ключа в ключ кластеризованного индекса - не единственный способ построить кластеризованный индекс в куче. У вас есть другие частые запросы, в которых запрашиваются диапазоны по определенному столбцу? Типичными кандидатами являются такие столбцы, как date, state или deleted. Если вы это сделаете, вам следует подумать о том, чтобы сделать эти столбцы ключом кластеризованного индекса (он не должен быть уникальным), потому что это может помочь запросам, которые запрашивают диапазоны, например «все записи за вчерашний день».

Единственный сценарий, в котором кучи имеют значительное преимущество в производительности, - это вставки, особенно массовые вставки. ЕСЛИ ваша нагрузка невелика, вам определенно следует использовать кластерный индекс. См. Рекомендации по созданию кластерного индекса.

Переходя к вашим точкам:

Почти наверняка захочется установить кластерный индекс для каждой таблицы в вашей базе данных. Если в таблице его нет. Производительность наиболее распространенных запросов лучше.

Кластеризованный индекс, который может удовлетворять требованиям диапазона для большинства запросов, действительно значительно повысит производительность. Кластеризованный индекс, который может удовлетворять требованиям к порядку, тоже может быть полезен, но нигде так не полезен, как индекс, который может удовлетворять диапазону.

Кластерные индексы не всегда плохо работают с идентификаторами GUID ... все зависит от потребностей вашего приложения. Скорость INSERT пострадает, но скорость SELECT будет улучшена.

Будут улучшены только ВЫБОРЫ датчиков: SELECT ... WHERE key='someguid';. Запросы по идентификатору объекта и поиск по внешнему ключу выиграют от этого кластерного индекса. Индекс NC также может служить той же цели.

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

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

Кластерный индекс по GUID подходит в ситуациях, когда GUID имеет значение и повышает производительность за счет размещения связанных данных близко друг к другу http://randommadness.blogspot.com/2008/07/guids-and-clustered-indexes.html

Я не могу представить себе сценарий, в котором GUID может иметь «связанные данные». GUID - это типичная случайная структура, как два случайных идентификатора GUID могут быть связаны любым образом? Сценарий Дональда имеет лучшее решение: Устранение разногласий PAGELATCH для высоконагруженных рабочих нагрузок INSERT, что дешевле в реализации (требуется меньше места для хранения) и работает также для уникальных ключей (решение в связанной статье не будет работать для уникальных ключи, только для внешних ключей).

Кластеризация не влияет на скорость поиска - уникальный некластеризованный индекс должен выполнять свою работу.

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

person Remus Rusanu    schedule 13.12.2010
comment
Разве кластеризованные индексы не более эффективны для обычных запросов сканирования вне диапазона? То есть косвенное обращение пропускается. Не могли бы вы выяснить, почувствуем ли мы разницу в производительности? - person Carlo V. Dango; 14.12.2010
comment
Я редко видел, чтобы лишнее косвенное обращение играло сколько-нибудь значительную роль в производительности. Тупиковые ситуации гораздо опаснее, как описано здесь: rusanu.com/2009/05 / 16 / readwrite-deadlock - person Remus Rusanu; 14.12.2010

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

Практически все операции выполняются быстрее - да! даже вставки и обновления!

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

Лучше всего выбрать ключ, который будет узким, стабильным, уникальным и постоянно увеличивающимся - столбец типа INT IDENTITY идеально удовлетворяет всем этим требованиям.

Для получения более подробной информации о том, почему GUID не является хорошим ключом кластеризации, и о том, насколько он плох, см. Другие сообщения в блоге Кима Триппа:

person marc_s    schedule 13.12.2010
comment
да, я должен был сослаться на сообщение Kimberlys выше. Но каков ваш реальный жизненный опыт по этому поводу? Вы также заметили более быстрые приложения при переходе на CI? - person Carlo V. Dango; 14.12.2010
comment
@Carlo V. Dango: да, я изменил CI с GUID на INT IDENTITY и получил очень заметное увеличение скорости. К тому же скорость падает не так быстро. Уйти от плохого CI, безусловно, поможет! - person marc_s; 14.12.2010

Я могу порекомендовать книгу «Объяснение производительности SQL» - это книга об индексах на 200 страниц.

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

person Michael    schedule 20.11.2012