SQL первичный ключ и индекс - PullRequest
94 голосов
/ 20 января 2009

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

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

Редактировать: дополнительный вопрос - будет ли это вредно для дополнительной индексации первичного ключа?

Ответы [ 11 ]

63 голосов
/ 20 января 2009

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

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

44 голосов
/ 20 января 2009

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

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

Например, у вас есть таблица со многими столбцами, но вы запрашиваете только столбцы ID, Имя и Адрес. Взяв 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 выдаст вам результат только с использованием созданного вами индекса и ничего не будет читать из фактической таблицы.

27 голосов
/ 20 января 2009

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

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

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

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

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

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

17 голосов
/ 20 января 2009

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

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

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

7 голосов
/ 20 января 2009

Здесь отрывок из MSDN :

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

7 голосов
/ 20 января 2009

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

2 голосов
/ 20 января 2009

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

1 голос
/ 29 ноября 2018

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

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

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

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

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

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

  • NULL значения не допускаются в PRIMARY KEY, но допускаются в UNIQUE индексе; и как в операторах множеств (UNION, EXCEPT, INTERSECT), здесь NULL = NULL, что означает, что вы можете иметь только одно значение, так как два NULL s являются дубликатами друг друга;
  • может существовать только один PRIMARY KEY для таблицы, в то время как 999 могут быть созданы уникальные индексы
  • когда создается ограничение PRIMARY KEY, оно создается как кластеризованное, если в таблице уже нет кластеризованного индекса или NONCLUSTERED не используется в его определении; когда создается индекс UNIQUE, он создается как NONCLUSTERED, если только он не является специфическим для CLUSTERED, и такого уже не существует;
1 голос
/ 20 сентября 2011

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

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

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

0 голосов
/ 20 января 2009

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

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

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