Кластеризованные и некластеризованные - PullRequest
95 голосов
/ 30 сентября 2011

Мои знания более низкого уровня по 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 = ...

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

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

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

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

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

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

Ответы [ 5 ]

115 голосов
/ 30 сентября 2011

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

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

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

13 голосов
/ 30 сентября 2011

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

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

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

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

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

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

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

5 голосов
/ 30 сентября 2011

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

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

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

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

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

3 голосов
/ 08 июня 2015

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

Кластерный

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

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

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

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

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

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

0 голосов
/ 26 ноября 2013

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

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

  891 rows
  10 sec
  NONCLUSTERED 

  OR

  891 rows
  14 sec
  CLUSTERED
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...