первичный ключ и индекс sql

106

Скажем, у меня есть строка идентификатора (int) в базе данных, установленная в качестве первичного ключа. Если я часто запрашиваю идентификатор, мне также нужно его индексировать? Или первичный ключ означает, что он уже проиндексирован?

Причина, по которой я спрашиваю, заключается в том, что в MS SQL Server я могу создать индекс по этому идентификатору, который, как я уже сказал, является моим первичным ключом.

Изменить: дополнительный вопрос - не повредит ли дополнительное индексирование первичного ключа?

Данифо
источник

Ответы:

73

Вы правы, сбивает с толку тот факт, что SQL Server позволяет создавать повторяющиеся индексы для одного и того же поля (полей). Но тот факт, что вы можете создать еще один, не означает, что индекс PK также еще не существует.

Дополнительный индекс не приносит пользы, но единственный вред (очень небольшой) - это дополнительный размер файла и накладные расходы на создание строк.

dkretz
источник
39
Повреждение неиспользуемых индексов действительно очень вредно. Во-первых, индексы занимают место в хранилище. Во-вторых, он замедляет запись и обновление. Всегда удаляйте индексы, которые не собираетесь использовать.
Pacerier 06
50

Как уже говорили все, первичные ключи индексируются автоматически.

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

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

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

Итак, когда вы используете этот запрос:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server выдаст результат только с использованием созданного вами индекса и не будет читать ничего из реальной таблицы.

красный клевер
источник
28

ПРИМЕЧАНИЕ. Этот ответ касается разработки корпоративного класса. в целом .

Это проблема СУБД, а не только SQL Server, и ее поведение может быть очень интересным. Во-первых, хотя первичные ключи обычно индексируются автоматически (однозначно), это НЕ является абсолютным. Бывают случаи, когда важно, чтобы первичный ключ НЕ индексировался однозначно.

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

Теперь самое интересное - когда вам НЕ нужен уникальный индекс первичного ключа? Вы не хотите и терпеть не можете, когда ваша таблица получает достаточно данных (строк), чтобы сделать обслуживание индекса слишком дорогим. Это зависит от оборудования, механизма СУБД, характеристик таблицы и базы данных, а также от загрузки системы. Однако обычно он начинает проявляться, когда таблица достигает нескольких миллионов строк.

Существенная проблема заключается в том, что каждая вставка строки или обновление столбца первичного ключа приводит к сканированию индекса для обеспечения уникальности. Это уникальное сканирование индекса (или его эквивалент в любой СУБД) становится намного дороже по мере роста таблицы, пока не станет доминировать над производительностью таблицы.

Я много раз сталкивался с этой проблемой с таблицами размером до двух миллиардов строк, 8 ТБ памяти и 40 миллионами вставок строк в день. Мне было поручено перепроектировать задействованную систему, что включало удаление уникального индекса первичного ключа практически в качестве первого шага. Действительно, снижение этого индекса было необходимо в производственной среде просто для восстановления после простоя, прежде чем мы даже приблизились к редизайну. Этот редизайн включал поиск других способов гарантировать уникальность первичного ключа и обеспечить быстрый доступ к данным.

Роб Уильямс
источник
Что, если ключ является ключом автоинкремента int или bigint? Достаточно ли умен SQL Server, чтобы в этом случае не выполнять сканирование уникального индекса?
quillbreaker
1
@quillbreaker: уникальность IDENTITYполя не гарантируется. В конце концов, пользователи могут вставлять повторяющиеся значения, если они являются пользователем IDENTITY_INSERT.
Я знаю, что это древняя тема, но я не понимаю, как сканирование уникальности одного индекса могло бы стать такой нагрузкой на систему. Сканирование дерева B + должно быть O (log n) * v, где v - это ограниченные накладные расходы для фрагментации индекса, несовершенного баланса дерева и т. Д. Таким образом, 2 миллиарда строк будут логарифмической базой 2 из 2 000 000 000 (примерно 31 поиск) раз, скажем, 2, 3 или даже 10. 40 миллионов вставок в день - это около 462 / сек, ~ 100 операций ввода-вывода на вставку ... Ааа ... Ох. Понимаю. И это было до массового распространения SSD.
Чарльз Бернс
Если вы не сбросите ограничение уникальности, не будут ли накладные расходы на проверку каждой строки на уникальность намного больше?
Макс Candocia
21

По умолчанию первичные ключи всегда индексируются.

Вы можете определить первичный ключ в SQL Server 2012 с помощью SQL Server Management Studio или Transact-SQL. При создании первичного ключа автоматически создается соответствующий уникальный, кластерный или некластеризованный индекс.

http://technet.microsoft.com/en-us/library/ms189039.aspx

Jcollum
источник
9

Вот отрывок из MSDN :

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

MicSim
источник
8

PK станет кластеризованным индексом, если вы не укажете некластеризованный

SQLMenace
источник
3

Объявление ограничения PRIMARY KEYили UNIQUEзаставляет SQL Server автоматически создавать индекс.

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

Отсюда создание ограничения будет:

  • вызвать создание индекса с тем же именем
  • запретить удаление созданного индекса, так как ограничение не может существовать без него

и в то же время удаление ограничения приведет к удалению связанного индекса.

Итак, есть ли разница между a PRIMARY KEYили UNIQUE INDEX:

  • NULLзначения не разрешены PRIMARY KEY, но разрешены в UNIQUEиндексе; и, как в операторах множества (UNION, EXCEPT, INTERSECT), здесь NULL = NULLэто означает, что вы можете иметь только одно значение, поскольку два NULLs находятся как дубликаты друг друга;
  • только один PRIMARY KEYможет существовать в таблице, в то время как можно создать 999 уникальных индексов
  • когда PRIMARY KEYсоздается ограничение, оно создается как кластеризованное, если в таблице уже нет кластеризованного индекса или NONCLUSTEREDне используется в его определении; когда UNIQUEсоздается индекс, он создается так, как NONCLUSTEREDесли бы он не был специфическим, CLUSTEREDи он уже не существует;
gotqn
источник
2

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

Э.Дж. Бреннан
источник
1

В SQL Server первичный ключ обычно индексируется автоматически. Это правда, но это не гарантирует более быстрого запроса. Первичный ключ обеспечит отличную производительность, если в качестве первичного ключа используется только одно поле. Но если в качестве первичного ключа используется несколько полей, то индекс основан на этих полях.

Например: поля A, B, C являются первичным ключом, поэтому, когда вы выполняете запрос на основе этих 3 полей в вашем WHERE CLAUSE, производительность хорошая, НО когда вы хотите запросить только поле C в WHERE CLAUSE, вы не будет хорошей производительности. Таким образом, чтобы повысить производительность, вам нужно будет вручную проиндексировать поле C.

В большинстве случаев вы не увидите проблему, пока не достигнете более 1 миллиона записей.

Сусанто Симан
источник
0

У меня огромная база данных без (отдельного) индекса.

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

Грант
источник
Это связано с тем, что PK является кластеризованным индексом, посмотрите на свой план запроса
SQLMenace,
0

первичные ключи автоматически индексируются

вы можете создавать дополнительные индексы с помощью pk в зависимости от вашего использования

  • index zip_code, id может быть полезным, если вы часто выбираете по zip_code и id
мсон
источник