Подтвердить что ты не робот

Должен ли я избавиться от кластеризованных индексов на столбцах Guid

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

По умолчанию SQL Server помещает кластерный индекс в столбцы первичного ключа. Я понимаю, что это глупая идея для столбцов GUID, и что некластеризованные индексы лучше.

Как вы думаете, следует ли мне избавиться от всех кластерных индексов и заменить их некластеризованными индексами?

Почему бы не использовать SQL-тюнер в качестве рекомендации?

4b9b3361

Ответ 1

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

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

Так что да, не класть индекс на GUID.

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

Ответ 2

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

По каким полям должен быть установлен кластеризованный индекс, зависит от самой таблицы и ожидаемых схем использования запросов к таблице. Почти в каждом случае вы, вероятно, хотите, чтобы кластеризованный индекс находился в столбце или комбинации уникальных столбцов, т.е. (Альтернативный ключ), потому что если это не так, SQL добавит уникальное значение в конец любого поля вы выбираете в любом случае. Если в вашей таблице есть столбец или столбцы, которые будут часто использоваться запросами для выбора или фильтрации нескольких записей (например, если ваша таблица содержит транзакции продаж, а ваше приложение будет часто запрашивать транзакции продаж по идентификатору продукта или даже лучше, таблица сведений о счете-фактуре, где почти в каждом случае вы будете извлекать все подробные записи для определенного счета-фактуры, или таблица счетов-фактур, в которой вы часто получаете все счета-фактуры для конкретного клиента... Это верно, если вы будете выбраны большими количество записей по одному значению или диапазону значений)

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

Причина всего этого основана на понимании внутренней структуры индекса базы данных. Эти индексы называются индексами сбалансированного дерева (B-Tree). они похожи на двоичное дерево, за исключением того, что каждый узел в дереве может иметь произвольное количество записей (и дочерних узлов) вместо двух. Отличительным признаком кластеризованного индекса является то, что конечные узлы кластерного индекса являются фактическими страницами данных физического диска самой таблицы. тогда как листовые узлы некластеризованного индекса просто "указывают" на страницы данных таблиц.

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

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

Для некластеризованного индекса он должен проходить индекс один раз для каждой строки, которую он извлекает...

ПРИМЕЧАНИЕ: РЕДАКТИРОВАТЬ
Чтобы решить проблему с последовательностью для столбцов Guid Key, имейте в виду, что SQL2k5 имеет NEWSEQUENTIALID(), которая фактически генерирует Guids "старым" последовательным способом.

или вы можете исследовать алгоритм алгоритма COMB Джимми Нильсена, который реализован в коде на стороне клиента:

COMB направляющие

Ответ 3

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

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

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

Ответ 5

Если вы используете NewId(), вы можете переключиться на NewSequentialId(). Это должно помочь вставить perf.

Ответ 6

Да, нет смысла указывать кластерный индекс на случайное значение.

Вероятно, вам нужны кластерные индексы SOMEWHERE в вашей базе данных. Например, если у вас есть таблица "Автор" и таблица "Книга" с внешним ключом "Автор", и если у вас есть запрос в приложении, который говорит "выберите... из книги, где AuthorId =..", тогда вы будете читать набор книг. Это будет быстрее, если эти книги будут физически рядом друг с другом на диске, так что голова диска не должна отскакивать от сектора к сектору, собирающего все книги этого автора.

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

Внесите изменения.

И затем проверьте, потому что вы никогда не знаете...

Ответ 8

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

Ответ 9

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

Ответ 10

Как упоминалось выше, избегайте использования случайного идентификатора в кластерном индексе - вы не получите преимуществ кластеризации. Фактически, у вас будет повышенная задержка. Избавиться от них - солидный совет. Также имейте в виду, что newsequentialid() может быть чрезвычайно проблематичным в сценарии репликации с несколькими мастерами. Если в базе данных A и B вызывается newsequentialid() перед репликацией, у вас будет конфликт.