Мои знания SQL на более низком уровне (Server 2008) ограничены, и теперь наши администраторы баз данных оспаривают их. Позвольте мне объяснить (я упомянул очевидные утверждения в надежде, что я прав, но если вы видите что-то не так, скажите мне) сценарий:
У нас есть стол, в котором хранятся «Судебные приказы» для людей. Когда я создал таблицу (Имя: 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 = ...
Затем я применил КЛАСТЕРНЫЙ индекс для PersonId. Причина заключалась в том, чтобы сгруппировать заказы для конкретного человека физически, так как подавляющее большинство работы - это получение заказов для человека. Так,select from mytable where personId = ...
Меня сейчас на этом остановили. Мне сказали, что мы должны поместить кластерный индекс на первичный ключ, а нормальный индекс на personId. Мне это кажется очень странным. Во-первых, зачем помещать кластерный индекс в уникальный столбец? что это за кластеризация? Неужели это пустая трата кластерного индекса? Я бы подумал, что нормальный индекс будет использоваться для уникального столбца. Кроме того, кластеризация индекса означает, что мы не можем кластеризовать другой столбец (по одному на таблицу, верно?).
Причина, по которой мне сказали, что я совершил ошибку, состоит в том, что они считают, что кластеризованный индекс для PersonId замедлит вставку. При 5% -ном приросте скорости выбора мы бы получили 95% -ное снижение скорости при вставках и обновлениях. Это правильно и верно?
Они говорят, что, поскольку мы группируем personId, SQL Server должен переупорядочивать данные, когда мы вставляем или изменяем PersonId.
Тогда я спросил, почему в SQL должна быть концепция КЛАСТЕРИРОВАННОГО ИНДЕКСА, если он такой медленный? Это так медленно, как они говорят? Как мне настроить индексы для достижения оптимальной производительности? Я бы подумал, что SELECT используется больше, чем INSERT ... но они говорят, что у нас проблемы с блокировкой INSERTS ...
Надеюсь, кто-нибудь может мне помочь.
Ответы:
Различие между кластеризованным и некластеризованным индексом заключается в том, что кластерный индекс определяет физический порядок строк в базе данных . Другими словами, применение кластеризованного индекса к
PersonId
означает, что строки будут физически отсортированыPersonId
в таблице, позволяя поиску по этому индексу переходить прямо к строке (а не к некластеризованному индексу, который направит вас к место, добавив дополнительную ступеньку).Тем не менее, необычно, что первичный ключ не является кластеризованным индексом, но это не является чем-то необычным . Проблема с вашим сценарием на самом деле противоположна тому, что вы предполагаете: вам нужны уникальные значения в кластеризованном индексе, а не дубликаты. Поскольку кластеризованный индекс определяет физический порядок строки, если индекс находится в неуникальном столбце, то сервер должен добавить фоновое значение к строкам, которые имеют повторяющееся значение ключа (в вашем случае любые строки с одинаковым
PersonId
), чтобы комбинированное значение (ключ + значение фона) было уникальным.Единственное, что я предлагаю, - это не использовать
CourtOrderId
столбец суррогатного ключа (ваш ) в качестве первичного ключа, а вместо этого использовать составной первичный ключPersonId
и некоторые другие столбцы или набор столбцов с уникальной идентификацией. Если это невозможно (или нецелесообразно), тогда включите кластерный индексCourtOrderId
.источник
PersonId
. Он логически отсортированPersonId
, любое несоответствие между логическим и физическим порядком - это степень логической фрагментации.Я ни в коем случае не эксперт по SQL ... так что воспринимайте это как точку зрения разработчика, а не как точку зрения администратора баз данных ...
Вставки в кластеризованные (физически упорядоченные) индексы, которые не находятся в последовательном порядке, вызывают дополнительную работу для вставок / обновлений. Кроме того, если у вас одновременно выполняется много вставок, и все они происходят в одном месте, возникает конфликт. Ваша конкретная производительность зависит от ваших данных и способа доступа к ним. Общее практическое правило - построить кластерный индекс на основе наиболее уникального узкого значения в таблице (обычно PK).
Я предполагаю, что ваш PersonId не изменится, поэтому обновления здесь не применяются. Но рассмотрим снимок нескольких строк с PersonId 1 2 3 3 4 5 6 7 8 8
Теперь вставьте 20 новых строк для PersonId из 3. Во-первых, поскольку это не уникальный ключ, сервер добавляет несколько дополнительных байтов к вашему значению (за кулисами), чтобы сделать его уникальным (что также добавляет дополнительное пространство), а затем местоположение, где они должны быть изменены. Сравните это со вставкой автоматически увеличивающегося PK, где вставки происходят в конце. Нетехническое объяснение, скорее всего, сводится к следующему: меньше работы по «перетасовке листьев», если она естественным образом увеличивает значения в конце таблицы по сравнению с переделкой местоположения существующих элементов в этом месте при вставке ваших элементов.
Теперь, если у вас возникли проблемы со вставками, вы, вероятно, вставляете сразу несколько одинаковых (или похожих) значений PersonId, что вызывает эту дополнительную работу в разных местах по всей таблице, и фрагментация вас убивает. Обратной стороной переключения на кластеризацию PK в вашем случае является то, что сегодня у вас возникли проблемы со вставкой на PersonIds, которые различаются по значению, разбросанному по всей таблице, если вы переключите свой кластеризованный индекс на PK, и все вставки теперь происходят в одном местоположение, то ваша проблема может усугубиться из-за повышенной концентрации конфликтов. (С другой стороны, если ваши вставки сегодня не разбросаны повсюду, а все обычно сгруппированы в схожих областях, то ваша проблема, вероятно, упростится, если переключить кластерный индекс с PersonId на ПК, потому что вы минимизируете фрагментация.)
Ваши проблемы с производительностью следует анализировать с учетом вашей конкретной ситуации и принимать эти типы ответов только как общие рекомендации. Лучше всего положиться на администратора базы данных, который может точно определить, в чем заключаются ваши проблемы. Похоже, у вас есть проблемы с конкуренцией за ресурсы, которые могут выходить за рамки простой настройки индекса. Это могло быть признаком гораздо более серьезной проблемы. (Вероятные проблемы с дизайном ... в противном случае ограничения ресурсов.)
В любом случае удачи!
источник
Некоторые авторы предлагают не «тратить зря»
CI
наidentity
столбец, если есть альтернатива, которая принесет пользу запросам диапазона.В рекомендациях по созданию кластерного индекса MSDN ключ следует выбирать в соответствии со следующими критериями.
Ваша
CourtOrderID
колонка встречается2
. ВашаPersonId
встречает1
и3
. Поскольку большинство строк всеuniqueifier
равно будут добавлены, вы можете просто объявить его уникальным и использовать,PersonId,CourtOrderID
поскольку он будет той же ширины, но будет более полезен, поскольку ключ кластеризованного индекса добавляется ко всем NCI в качестве локатора строк, и это позволит их, чтобы охватить больше запросов.Основная проблема с использованием
PersonId,CourtOrderID
в качестве CI заключается в том, что, скорее всего, последует логическая фрагментация (и это особенно влияет на запросы диапазона, которым вы пытаетесь помочь), поэтому вам нужно будет отслеживать коэффициент заполнения и уровни фрагментации и чаще выполнять обслуживание индекса.источник
Это объясняется по следующей ссылке: https://msdn.microsoft.com/en-us/ms190457.aspx
Кластеризованный
Кластерные индексы сортируют и сохраняют строки данных в таблице или представлении на основе их значений ключей. Это столбцы, включенные в определение индекса. Для каждой таблицы может быть только один кластеризованный индекс, потому что сами строки данных можно сортировать только в одном порядке.
Единственный раз, когда строки данных в таблице хранятся в отсортированном порядке, - это когда таблица содержит кластеризованный индекс. Когда таблица имеет кластерный индекс, таблица называется кластеризованной таблицей. Если таблица не имеет кластеризованного индекса, ее строки данных хранятся в неупорядоченной структуре, называемой кучей.
Некластеризованный
Некластеризованные индексы имеют структуру, отдельную от строк данных. Некластеризованный индекс содержит значения ключей некластеризованного индекса, и каждая запись значения ключа имеет указатель на строку данных, содержащую значение ключа .
Указатель из строки индекса в некластеризованном индексе на строку данных называется локатором строки. Структура локатора строк зависит от того, хранятся ли страницы данных в куче или в кластерной таблице. Для кучи локатор строки - это указатель на строку. Для кластеризованной таблицы указателем строки является ключ кластеризованного индекса.
Вы можете добавить неключевые столбцы на конечный уровень некластеризованного индекса, чтобы обойти существующие ограничения ключа индекса, 900 байт и 16 ключевых столбцов, и выполнить полностью покрытые, индексированные запросы.
источник
Некоторая база данных с некоторыми неприятными выборами присоединяется к хранимой процедуре - только разница - это индекс
ИНДЕКСЫ - кластеризованные против некластеризованных
источник