0

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

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

Так вот:

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

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

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

ответ

2

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

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

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

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

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

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

0

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

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

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

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

1

Ваше предположение о clustered vs non-clustered довольно хорошо

Кроме того, представляется, что первичный ключ навязывает не являющееся uniquenes неопределенного, в то время как уникальный индекс не навязывает, не действующие Null primary vs unique

1

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

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

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

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

  • должен быть уникальным (если нет, то SQL Server будет добавить 4-байтовый "uniqueifier")
  • должен быть стабильным (никогда не меняется)
  • должен быть как можно меньше (INT лучше)
  • должна быть постоянно растет (думаю: IDENTITY)

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

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

Marc

1

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

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

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

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

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

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

Такое же поведение относится к индексам 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.