Использование некластеризованного индекса в столбце типа guid в SQL Server

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

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

Я читал, что добавление кластеризованных индексов в столбцы типа GUID — очень плохое решение, потому что индекс нужно будет постоянно реконструировать, чтобы он был эффективным. Однако мне было интересно, есть ли какой-либо ущерб от использования некластеризованного индекса в описанном выше сценарии? Или разумно предположить, что это поможет производительности? Я могу предоставить больше информации, если это необходимо.


person Christian    schedule 10.12.2012    source источник
comment
Индексы — это функция производительности, а внешние ключи — нет. FK — это функция Relational Integrity.   -  person RBarryYoung    schedule 10.12.2012


Ответы (5)


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

Это правда, что uniqueidentifier плохо подходит для индексов по упомянутым вами причинам, но это никоим образом не означает, что вы не должны не создавать эти индексы. Если возможно, рекомендуется изменить тип данных на INT или BIGINT. Используя NEWSEQUENTIALID() или UuidCreateSequential для их создания поможет решить проблемы с фрагментацией. Если все альтернативы не работают, вам, возможно, придется выполнять операции обслуживания индекса (перестроение, реорганизация) чаще, чем для других индексов. Но ни один из этих недостатков ни в коем случае не перевешивает преимущества наличия индекса!

person Remus Rusanu    schedule 10.12.2012
comment
Я не уверен, смогу ли я изменить тип данных, который мы использовали, поскольку мы приближаемся к крайнему сроку, и я не знаю, каковы будут последствия перехода на int в этот момент (многие хранимые процедуры используют столбец так что это потребует много обновлений относительно типа данных). Когда вы говорите об индексе «любого типа», вы имеете в виду, что индекс соответствующего столбца любого типа данных повышает производительность запросов к таблице? Кроме того, считаете ли вы, что некластеризованный индекс для uniqueidentifier является лучшим выбором, чем кластеризованный, как указано в ответе ниже? - person Christian; 10.12.2012
comment
Если вы имеете в виду мой ответ. Зарезервируйте кластеризованный индекс для PK (таблица, на которую указывает FK). - person paparazzo; 10.12.2012
comment
Под «любым типом» я подразумеваю, что даже самый плохой индексируемый тип данных, о котором вы только можете подумать (например, даже varchar(900)), часто лучше иметь индекс, чем не иметь его. Если необходим индекс (== операции поиска), то просто нет альтернативы не иметь индекса. Конечно, лучше улучшить тип данных, если это возможно. Как всегда, между белым и черным есть много оттенков серого, но отправной точкой должен быть «индекс необходим, как мы можем снизить его влияние?» - person Remus Rusanu; 10.12.2012
comment
И да, индекс NC для непоследовательного уникального идентификатора лучше кластерного с точки зрения структуры и работоспособности индекса. Однако, если столбец идентификатора uniquiedtifier является одним из наиболее часто используемых поисковых запросов (поисков), то он должен быть кластеризованным, даже за счет плохо структурированного (фрагментированного) индекса, поскольку он используется в качестве индекса NC и должен искать остальные. столбцов для каждой строки может противоречить своему назначению. См. sqlskills.com/blogs/kimberly/category/the-tipping. -point.aspx - person Remus Rusanu; 10.12.2012

Два исполнения:
— вставить
— выбрать

Индекс должен улучшить выбор

Индекс замедляет вставку.
Если вставки упорядочены, индекс не фрагментируется.
Если вставки не упорядочены, индекс фрагментируется.
Фрагментация индекса замедляет как вставку, так и выборку.
Через обслуживание можно дефрагментировать индекс.

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

В самой таблице FK GUID не является хорошим кандидатом для PK (кластеризованного индекса).
С GUID в качестве PK, который индексирует фрагменты при вставке.
Int или последовательный идентификатор являются лучшими кандидатами, поскольку они не будут фрагментировать PK при вставке.
Но ничего страшного, просто дефрагментируйте эти таблицы.

person paparazzo    schedule 10.12.2012
comment
Спасибо Вам за информацию. Как замедление при вставке соотносится с увеличением производительности при извлечении? Полностью ли они уравновешены, способствуют увеличению или уменьшению, или это полностью зависит от случая? После развертывания приложения мы не сможем получить доступ к базе данных, можно ли автоматизировать задачи в базе данных при ее создании?/развернуть? - person Christian; 10.12.2012
comment
Варьируется. Правильно спроектированный и поддерживаемый индекс не удвоит время вставки. На большом столе выбор может быть увеличен в 10 и более раз. Если у вас больше выборок, чем вставка/обновление, и столбец находится в предложении where или join, тогда кандидат на индекс. Я обычно индексирую и FK. Что касается невозможности доступа к этой базе данных после ее развертывания, то больше причин для того, чтобы ПК был целым или последовательным. - person paparazzo; 10.12.2012

Да, вам лучше изменить индекс Guid с кластерного на некластеризованный. Guid по-прежнему может быть первичным ключом, и вам не нужно менять свой запрос/исходный код. Отсутствие переупорядочения данных и повышение производительности.

В таких базах данных, как SQL Azure, наличие кластерного индекса обязательно. Таким образом, вы можете использовать поле даты/даты и времени. Создание дополнительного столбца int-identity/autoincrement не требуется, так как некоторые разработчики в одной команде склонны использовать те и другие GUID. Результат - несовместимое приложение. Так что держите только GUID.. точка!

Говоря о последовательных гидах, я думаю, что гиды лучше создавать из кода, чем из базы данных. Современные DAL и шаблоны репозиториев не предпочитают зависимости от БД для CRUD. например сценарий: запрос linq и автоматические сборки с модульным тестированием без зависимости от БД. И создавать последовательное руководство самостоятельно - не очень хорошая идея (по крайней мере, для меня). Таким образом, Guid в качестве первичного ключа с некластеризованным индексом — лучший вариант.

У меня есть поддержка от Microsoft по некластеризованной теме http://blogs.msdn.com/b/sqlazure/archive/2010/05/05/10007304.aspx

Отредактировано: поддержка исчезла ("Ресурс не найден")

person Blue Clouds    schedule 24.11.2013

Обычно это помогало производительности. Но вы можете захотеть создать индекс с коэффициентом заполнения менее 100%, чтобы не так часто приходилось сталкиваться с неизбежным разделением страниц. Регулярное обслуживание индекса, безусловно, будет плюсом.

person Matt Whitfield    schedule 10.12.2012

Да, некластеризованный индекс был бы идеальным для вашей ситуации. Базовым является B-дерево, как и кластерный индекс, но базовые данные в таблице не отсортированы, поэтому проблем с непоследовательным характером GUID не существует. Индекс NC существует отдельно от таблицы.

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

Соответствующий MSDN: http://msdn.microsoft.com/en-us/library/ms177484(v=sql.105).aspx

person Fredrik E    schedule 10.12.2012
comment
но он не отсортирован, так что проблем с непоследовательным характером GUID не существует Это на самом деле неправильно. Индексы NC отсортированы, как и все BTree. Они также страдают от всех проблем с гидом. - person Remus Rusanu; 11.12.2012
comment
Ах, это не то, что я имел в виду. Базовые данные не сортируются в некластеризованном индексе, поэтому таблица не страдает от проблем с guid. Я обновил свой ответ. Спасибо, что указали на это. - person Fredrik E; 13.12.2012