Первичный ключ или уникальный индекс?

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

Я разрабатываю новую базу данных для нового проекта, и у меня есть дилемма:

В теории БД первичный ключ - это фундаментальный элемент, который ОК, но в проектах REAL есть преимущества и недостатки обоих?

Что вы используете в проектах?

EDIT:... а как насчет первичных ключей и репликации на сервере MS SQL?

Ответ 1

Что такое уникальный индекс?

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

CREATE TABLE table1 (foo int, bar int);
CREATE UNIQUE INDEX ux_table1_foo ON table1(foo);  -- Create unique index on foo.

INSERT INTO table1 (foo, bar) VALUES (1, 2); -- OK
INSERT INTO table1 (foo, bar) VALUES (2, 2); -- OK
INSERT INTO table1 (foo, bar) VALUES (3, 1); -- OK
INSERT INTO table1 (foo, bar) VALUES (1, 4); -- Fails!

Duplicate entry '1' for key 'ux_table1_foo'

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

В MySQL уникальное ограничение допускает несколько NULL.

Можно создать уникальный индекс для нескольких столбцов.

Первичный ключ или уникальный индекс

То же самое:

  • Первичный ключ подразумевает уникальный индекс.

Вещи, которые отличаются друг от друга:

  • Первичный ключ также подразумевает NOT NULL, но уникальный индекс может быть нулевым.
  • Может быть только один первичный ключ, но может быть несколько уникальных индексов.
  • Если кластерный индекс не определен, первичный ключ будет кластеризованным индексом.

Ответ 2

Вы можете видеть это следующим образом:

Основной ключ IS Unique

Уникальное значение не должно быть представлением элемента

Значение?; Ну, первичный ключ используется для идентификации элемента, если у вас есть "Лицо", которое вы хотели бы иметь персональный идентификационный номер (SSN или такой), который является первичным для вашего лица.

С другой стороны, у человека может быть уникальное электронное письмо, но он не идентифицирует человека.

У меня всегда есть первичные ключи, даже в таблицах отношений (таблица таблицы/таблицы/таблицы), которые у меня могут быть. Зачем? Ну, мне нравится следовать стандарту при кодировании, если у "Person" есть идентификатор, у автомобиля есть идентификатор, ну, тогда Person → Car также должен иметь идентификатор!

Ответ 3

Внешние ключи работают с уникальными ограничениями, а также с первичными ключами. Из книг в Интернете:

Ограничение FOREIGN KEY не имеет быть связанным только с ОСНОВНЫМ КЛЮЧОМ ограничение в другой таблице; оно может также можно определить для ссылки на столбцов УНИКАЛЬНОГО ограничения в другая таблица

Для транзакционной репликации вам нужен первичный ключ. Из книг в Интернете:

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

Оба ответа для SQL Server 2005.

Ответ 4

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

В качестве примера у меня есть следующие таблицы:

CREATE TABLE toll_booths (
    id            INTEGER       NOT NULL PRIMARY KEY,
    name          VARCHAR(255)  NOT NULL,
    ...
    UNIQUE(name)
)

CREATE TABLE cars (
    vin           VARCHAR(17)   NOT NULL PRIMARY KEY,
    license_plate VARCHAR(10)   NOT NULL,
    ...
    UNIQUE(license_plate)
)

CREATE TABLE drive_through (
    id            INTEGER       NOT NULL PRIMARY KEY,
    toll_booth_id INTEGER       NOT NULL REFERENCES toll_booths(id),
    vin           VARCHAR(17)   NOT NULL REFERENCES cars(vin),
    at            TIMESTAMP     DEFAULT CURRENT_TIMESTAMP NOT NULL,
    amount        NUMERIC(10,4) NOT NULL,
    ...
    UNIQUE(toll_booth_id, vin)
)

У нас есть две таблицы сущностей (toll_booths и cars) и таблица транзакций (drive_through). В таблице toll_booth используется суррогатный ключ, поскольку он не имеет естественного атрибута, который не может быть изменен (имя можно легко изменить). В таблице cars используется естественный первичный ключ, поскольку он имеет неизменяемый уникальный идентификатор (vin). Таблица транзакций drive_through использует суррогатный ключ для упрощения идентификации, но также имеет уникальное ограничение на атрибуты, которые гарантированно будут уникальными на момент внесения записи.

http://database-programmer.blogspot.com содержит несколько замечательных статей по этому вопросу.

Ответ 5

Нет недостатков первичных ключей.

Чтобы добавить только некоторую информацию в ответы @MrWiggles и @Peter Parker, когда таблица не имеет первичного ключа, например, вы не сможете редактировать данные в некоторых приложениях (они в конечном итоге скажут, что sth вроде не может редактировать/удалять данные без первичного ключа). Postgresql позволяет использовать несколько значений NULL в столбце UNIQUE, PRIMARY KEY не разрешает NULL. Также некоторые ORM, которые генерируют код, могут иметь некоторые проблемы с таблицами без первичных ключей.

UPDATE:

Насколько я знаю, невозможно реплицировать таблицы без первичных ключей в MSSQL, по крайней мере без проблем (details).

Ответ 6

Если что-то является первичным ключом, в зависимости от вашего механизма БД, вся таблица сортируется по первичному ключу. Это означает, что поисковые запросы намного быстрее на первичном ключе, потому что он не должен делать разыменование, как это имеет отношение к любому другому типу индекса. Кроме того, это просто теория.

Ответ 7

Пока вы не разрешаете NULL для значения, они должны обрабатываться одинаково, но значение NULL обрабатывается по-разному в базах данных (AFAIK MS-SQL не допускает более одного (1) значения NULL, mySQL и Oracle позволяет это, если столбец UNIQUE) Таким образом, вы должны определить этот столбец NOT NULL UNIQUE INDEX

Ответ 8

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

Уникальные индексы не являются частью стандарта SQL. Конкретная реализация СУБД определит, каковы последствия объявления уникального индекса.

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

Я предпочитаю объявление первичного ключа. Это приводит к запрету NULL в ключевом столбце (столбцах), а также запрещении дублирования. Я также одобряю объявление ограничений ССЫЛКИ для обеспечения целостности объектов. Во многих случаях объявление индекса на coulmn (s) внешнего ключа ускоряет объединение. Этот тип индекса вообще не должен быть уникальным.

Ответ 9

В дополнение к тому, что говорили другие ответы, некоторые базы данных и системы могут требовать наличия первичного представления. На ум приходит одна ситуация; при использовании репликации предприятия с Informix необходимо, чтобы PK присутствовал в таблице для участия в репликации.

Ответ 10

Я почти никогда не создаю таблицу без числового первичного ключа. Если есть также естественный ключ, который должен быть уникальным, я также помещаю на него уникальный индекс. Соединения быстрее по целым числам, чем многоколоночные натуральные ключи, данные нужно менять только в одном месте (естественные ключи, как правило, нуждаются в обновлении, что плохо, когда они находятся в первичном ключе - отношения внешних ключей). Если вам понадобится репликация, используйте GUID вместо целого числа, но по большей части я предпочитаю ключ, который читается пользователем, особенно если им нужно увидеть его, чтобы отличить Джона Смита от Джона Смита.

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

Ответ 11

Есть некоторые недостатки CLUSTERED INDEXES против UNIQUE INDEXES.

Как уже было сказано, CLUSTERED INDEX физически упорядочивает данные в таблице.

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

В относительных небольших таблицах это нормально, но когда вы попадаете на таблицы с объемом данных в ГБ, а вставки/удаления влияют на сортировку, вы столкнулись с проблемами.

Ответ 12

Я понимаю, что первичный ключ и уникальный индекс с непустым ограничением одинаковы (*); и я полагаю, что один выбирает тот или иной, в зависимости от того, что спецификация явно заявляет или подразумевает (вопрос того, что вы хотите выразить и явно применять). Если для этого требуется уникальность и не-null, тогда сделайте его первичным ключом. Если это просто происходит, все части уникального индекса не являются нулевыми без каких-либо требований для этого, то просто сделайте его уникальным индексом.

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

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

Другие здесь упомянули репликацию БД, но я не знаю об этом.

Ответ 13

Уникальный индекс может иметь одно значение NULL. Он создает НЕ-КЛАСТЕРИРОВАННЫЙ ИНДЕКС. Первичный ключ не может содержать значение NULL. Он создает CLUSTERED INDEX.

Ответ 14

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

Ответ 15

Если бы это было до меня...

Вы должны удовлетворить требования базы данных и ваших приложений.

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

Затем вы добавите в таблицу хотя бы еще один уникальный индекс для использования вашим приложением. Это может быть индекс для employee_id, account_id или customer_id и т.д. Если возможно, этот индекс не должен быть составным.

Я бы предпочел индексы по нескольким областям индивидуально, а не комбинированные индексы. База данных будет использовать индексы одного поля всякий раз, когда предложение where включает эти поля, но она будет использовать составной только тогда, когда вы предоставляете поля в правильном порядке - это означает, что она не может использовать второе поле в составном индексе, если вы не предоставите как первое, так и второе в предложении where.

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

Это заботится о ваших требованиях к заявке.

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