Кластерный и некластерный

Мои более низкие знания SQL (Server 2008) ограничены, и сейчас наши администраторы баз данных сталкиваются с проблемой. Позвольте мне объяснить (я упомянул очевидные заявления в надежде, что я прав, но если вы видите что-то не так, скажите мне) сценарий:

У нас есть таблица, которая содержит "Приказы суда" для людей. Когда я создал таблицу, (Name: CourtOrder), я создал ее как:

CREATE TABLE dbo.CourtOrder
(
  CourtOrderID INT NOT NULL IDENTITY(1,1), (Primary Key)
  PersonId INT NOT NULL,
  + around 20 other fields of different types.
)

Затем я применил некластеризованный индекс к первичному ключу (для эффективности). Мои причины заключаются в том, что это уникальное поле (первичный ключ) и должно индексироваться, главным образом для целей выбора, поскольку мы часто Select from table where primary key = ...

Затем я применил индекс CLUSTERED для PersonId. Причина состояла в том, чтобы группировать заказы для определенного человека физически, поскольку подавляющее большинство работ получает заказы на человека. Итак, select from mytable where personId = ...

Я сейчас подтянулся. Мне сказали, что мы должны поместить кластеризованный индекс на первичный ключ и нормальный индекс на personId. Мне это очень странно. Во-первых, почему вы кладете кластерный индекс в уникальный столбец? что это кластеризация? Неужели это пустая трата кластеризованного индекса? Я бы поверила, что обычный индекс будет использоваться в уникальном столбце. Кроме того, кластеризация индекса будет означать, что мы не можем группировать другой столбец (по одному на таблицу, правда?).

Мне говорят, что я ошибся в том, что, полагая, что кластеризованный индекс в PersonId сделает медленные вставки. Для 5% -ного увеличения скорости выбора мы получим 95% -ное снижение скорости при вставках и обновлениях. Это верно и верно?

Они говорят, что, поскольку мы кластер personId, SQL Server должен переставлять данные, когда мы вставляем или вносим изменения в PersonId.

Итак, я спросил, почему SQL должен иметь концепцию CLUSTERED INDEX, если это так медленно? Это так медленно, как они говорят? Как мне настроить свои индексы для достижения оптимальной производительности? Я бы подумал, что SELECT используется больше, чем INSERT... но они говорят, что у нас есть проблемы с блокировкой на INSERTS...

Надеюсь, кто-то может мне помочь.

Ответ 1

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

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

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

Ответ 2

Я отнюдь не эксперт SQL... так что рассматривайте это как представление разработчика, а не представление DBA.

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

Я предполагаю, что ваш PersonId не будет меняться, поэтому обновления не вступают в игру здесь. Но рассмотрим снимок нескольких строк с PersonId из 1 2 3 3 4 5 6 7 8 8

Теперь вставьте 20 новых строк для PersonId 3. Сначала, поскольку это не уникальный ключ, сервер добавляет некоторые дополнительные байты в ваше значение (за кулисами), чтобы сделать его уникальным (что также добавляет дополнительное пространство), а затем место, где они будут проживать, должно быть изменено. Сравните это с тем, чтобы вставить автоинкрементный ПК, где вставки появляются в конце. Нетехническое объяснение, скорее всего, сведено к следующему: существует меньше работ "перетасовки листьев", если он, естественно, развивает более высокие значения в конце таблицы и перерабатывает местоположение существующих элементов в этом месте при вставке ваших элементов.

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

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

В любом случае, удачи!

Ответ 3

Некоторые авторы предлагают не "тратить" CI на столбец identity, если есть альтернатива, которая принесет пользу запросам диапазона.

Из MSDN Руководство по разработке кластерных указателей ключ следует выбирать в соответствии со следующими критериями

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

Ваш столбец CourtOrderID соответствует 2. Ваш PersonId соответствует 1 и 3. Поскольку в большинстве строк будет добавлен добавленный uniqueifier, вы можете просто объявить его уникальным и использовать PersonId,CourtOrderID, поскольку он будет иметь одинаковую ширину, но будет более полезен, поскольку кластерный индексный ключ будет добавлен ко всем NCI, поскольку локатор строк, и это позволит им покрывать больше запросов.

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

Ответ 4

Это объясняется в следующей ссылке: https://msdn.microsoft.com/en-us/ms190457.aspx

кластерного

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

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

Некластеризованный

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

  • Указатель из строки индекса в некластеризованном индексе в строку данных называется локатором строк. Структура локатора строк зависит от того, хранятся ли страницы данных в куче или кластеризованной таблице. Для кучи указатель строки является указателем на строку. Для кластеризованной таблицы локатор строк представляет собой кластерный индексный ключ.

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

Ответ 5

Некоторые db с некоторыми неприятными выборами, объединяются в хранимую процедуру - только diffrence - это индекс

ИНДЕКСЫ - кластерные и некластеризованные

  891 rows
  10 sec
  NONCLUSTERED 

  OR

  891 rows
  14 sec
  CLUSTERED