Первичный ключ или Уникальный индекс? - PullRequest
115 голосов
/ 28 января 2009

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

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

В теории БД первичный ключ является фундаментальным элементом, это нормально, но в РЕАЛЬНЫХ проектах каковы преимущества и недостатки обоих?

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

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

Ответы [ 15 ]

152 голосов
/ 27 мая 2010

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

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

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, но уникальный индекс может иметь значение NULL.
  • Может быть только один первичный ключ, но может быть несколько уникальных индексов.
  • Если кластерный индекс не определен, то первичным ключом будет кластеризованный индекс.
29 голосов
/ 28 января 2009

Вы можете видеть это так:

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

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

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

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

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

8 голосов
/ 28 января 2009

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

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

Для репликации транзакций необходим первичный ключ. Из Книг Онлайн:

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

Оба ответа предназначены для SQL Server 2005.

5 голосов
/ 28 января 2009

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

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

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 имеет несколько замечательных статей на эту тему.

4 голосов
/ 28 января 2009

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

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

UPDATE:

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

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

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

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

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

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

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

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

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

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

1 голос
/ 20 августа 2013

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

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

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

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

1 голос
/ 20 декабря 2012

Есть некоторые недостатки кластерных индексов по сравнению с уникальными индексами.

Как уже говорилось, КЛАСТЕРНЫЙ ИНДЕКС физически упорядочивает данные в таблице.

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

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

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