Избегайте создания кластерного индекса на основе инкрементирующего ключа

Я получил этот намек от mssqlcity.com. Однако я не могу понять его объяснения.

Избегайте создания кластерного индекса на основе инкрементирующего ключа

Например, если таблица имеет суррогат целочисленный первичный ключ, объявленный как ИДЕНТИФИКАЦИЯ и кластеризованный индекс созданный в этом столбце, то каждый временные данные вставляются в эту таблицу, строки будут добавлены в конец стол. Когда много строк будут добавлено "горячее пятно". Горячий spot "возникает, когда многие запросы пытаются чтение или запись данных в том же в то же время." Горячая точка" приводит к Узкое место ввода-вывода. Заметка. По умолчанию SQL Сервер создает кластерный индекс для ограничение первичного ключа. Итак, в этом случае, вы должны явно указать NONCLUSTERED, чтобы указать, что некластеризованный индекс создается для ограничение первичного ключа.

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

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

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

Ответ 1

Горячее пятно, на которое они ссылаются, не является проблемой в SQL Server 2005 и новее.

Что ИСПОЛЬЗУЕТСЯ, так это то, что все ваши данные записывались в одну область кластеризованного индекса и один и тот же сектор (сектора) на диске, из-за чего было создано сразу несколько грязных страниц (грязные страницы являются данными страницы, которые были изменены, но не привязаны к диску), а при запуске флеша или контрольной точки это может вызвать проблемы.

Более новые версии не испытывают такого поведения из-за изменений в архитектуре ввода-вывода (из того, что я понимаю).

Ответ 2

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

См. также https://dba.stackexchange.com/questions/1584/is-avoid-creating-a-clustered-index-based-on-an-incrementing-key-a-myth-from-sq

Цитата также идет вразрез с советом (с той же страницы):

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

Ответ 3

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

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

Если десять потоков вставляют десять записей в таблицу со столбцом IDENTITY, двигатель будет создавать десять записей журнала транзакций (записанных один за другим одним процессом с именем Log Writer), а затем, когда это время для CHECKPOINT, эти записи будут записаны на соответствующие страницы данных (также одним процессом, называемым CHECKPOINT).

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

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