SQL 2005: вопросы о ключах, индексах и ограничениях - PullRequest
0 голосов
/ 10 сентября 2009

У меня есть ряд вопросов о ключах, индексах и ограничениях в SQL, в частности, в SQL 2005. Я работаю с SQL около 4 лет, но мне никогда не удавалось получить однозначные ответы по этой теме, и всегда есть противоречивая информация о сообщениях в блогах и т. Д. В большинстве таблиц времени, которые я создаю и использую, просто есть столбец Identity, который является первичным ключом, и другие таблицы указывают на него через внешний ключ.

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

Итак, вот так:

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

Я вижу, что первичные ключи на самом деле являются просто кластеризованными индексами, которые являются уникальными (нужно ли их кластеризовать?). Что особенного в первичном ключе по сравнению с кластерным уникальным индексом?

Я также видел Ограничения, но я никогда не использовал их и действительно не смотрел на них. Мне сказали, что целью ограничений является то, что они предназначены для обеспечения целостности данных, тогда как индексы нацелены на производительность. Я также читал, что ограничения в любом случае фактически реализуются как индексы, поэтому они «одинаковы». Это не звучит правильно для меня. Чем отличаются ограничения для индексов?

Ответы [ 5 ]

2 голосов
/ 10 сентября 2009

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

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

Когда вы должны использовать один или другой? Итак, поскольку у вас может быть только один кластеризованный индекс, определите его по столбцам, что наиболее целесообразно, т. Е. При поиске клиентов по идентификатору в большинстве случаев задайте кластеризованный индекс по идентификатору. Некластеризованные индексы должны быть определены для столбцов, которые используются реже.

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

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

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

1 голос
/ 10 сентября 2009

У вас есть несколько вопросов. Я сломаю некоторые из них:

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

Иногда вас волнует, как организованы строки. Это зависит от ваших данных и того, как вы будете их использовать. Например, если ваш первичный ключ - uniqueidentifier, вы, возможно, не захотите, чтобы он был CLUSTERED, поскольку значения GUID по существу случайны. Это приведет к тому, что SQL будет случайным образом вставлять строки в таблицу, что приведет к разбиению страниц, что снизит производительность. Если значение вашего первичного ключа всегда будет последовательно увеличиваться (например, int IDENTITY), то вы, вероятно, захотите, чтобы оно было CLUSTERED, поэтому ваша таблица всегда будет расти в конце.

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

Мне сказали, что вставка и удаление медленны с некластеризованными индексами, поскольку дерево необходимо «перестроить». Я так понимаю, кластерные индексы не влияют на производительность таким образом?

На самом деле, обратное может быть правдой. Индексы NONCLUSTERED хранятся в виде отдельной структуры данных, но структура разработана таким образом, чтобы можно было вносить некоторые изменения без необходимости «перестроения». Когда индекс создается изначально, вы можете указать FILLFACTOR, который указывает, сколько свободного места оставить на каждой странице индекса. Это позволяет индексу терпеть некоторые изменения, прежде чем разделение страницы необходимо. Даже если разделение страниц должно произойти, оно влияет только на соседние страницы, а не на весь индекс.

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

На следующей странице MSDN говорится о FILLFACTOR и разбиениях страницы: http://msdn.microsoft.com/en-us/library/aa933139(SQL.80).aspx

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

Для обоих из них я думаю, что это больше о декларации ваших намерений. Когда вы называете что-то PRIMARY KEY, вы заявляете, что это основной метод идентификации данной строки. PRIMARY KEY физически отличается от CLUSTERED UNIQUE INDEX? Я не уверен. Поведение в основном такое же, но ваши намерения могут быть неясны для кого-то, работающего с вашей базой данных.

Что касается ограничений, существует много типов ограничений. Для UNIQUE CONSTRAINT, на самом деле нет разницы между этим и UNIQUE INDEX, кроме объявления вашего намерения. Существуют другие типы ограничений, которые не отображаются непосредственно на тип индекса, такие как CHECK ограничения, DEFAULT ограничения и FOREIGN KEY ограничения.

1 голос
/ 10 сентября 2009

Ваше предположение о кластеризованном и некластеризованном довольно хорошо

Также кажется, что первичный ключ применяет ненулевые уникальные значения, в то время как уникальный индекс не предписывает ненулевые первичные и уникальные

1 голос
/ 10 сентября 2009

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

Ключ кластеризации представляет собой физическую концепцию хранения SQL Server. Это специальный индекс, который используется не только для поиска и т. Д., Но также определяет физическую структуру ваших данных в вашей таблице. В печатной телефонной книге в культуре Западной Европы (за исключением, может быть, в Исландии) кластеризованным индексом будет «Фамилия, Фамилия».

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

Требования к ключу кластеризации:

  • должен быть уникальным (если нет, SQL Server добавит 4-байтовый «уникальный идентификатор»)
  • должен быть стабильным (никогда не меняется)
  • должно быть как можно меньше (INT лучше)
  • должно быть все больше (думайте: ИДЕНТИЧНОСТЬ)

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

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

Марк

0 голосов
/ 10 сентября 2009

У меня нет времени, чтобы подробно ответить на этот вопрос, так что немного информации о моей голове:

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

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

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

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