Как лучше всего использовать первичные ключи в таблицах? - PullRequest
235 голосов
/ 03 декабря 2008

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

  1. Столбец целочисленного идентификатора, который автоматически увеличивается.
  2. Уникальный идентификатор (GUID)
  3. столбец с короткими символами (x) или целым числом (или другим относительно небольшим числовым типом), который может служить столбцом идентификатора строки

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

По большей части все остальные таблицы будут иметь автоинкрементное целое число или первичный ключ с уникальным идентификатором.

Вопрос: -)

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

  • DateTime / символ
  • Дата и время / VARCHAR
  • символ / NVARCHAR / NVARCHAR

Есть ли веские доводы для этого? Я бы всегда определял столбец идентификаторов или уникальных идентификаторов для этих случаев.

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

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

Третий вопрос, помогающий мне расшифровать ответы: в тех случаях, когда для составного первичного ключа используются несколько столбцов, есть ли конкретное преимущество этого метода по сравнению с суррогатным / искусственным ключом? Я думаю в основном о производительности, обслуживании, администрировании и т. Д.

Ответы [ 21 ]

225 голосов
/ 03 декабря 2008

Я следую нескольким правилам:

  1. Первичные ключи должны быть настолько маленькими, насколько это необходимо. Предпочитайте числовой тип, потому что числовые типы хранятся в гораздо более компактном формате, чем символьные форматы. Это связано с тем, что большинство первичных ключей являются внешними ключами в другой таблице, а также используются в нескольких индексах. Чем меньше ваш ключ, тем меньше индекс, тем меньше страниц в кеше вы будете использовать.
  2. Первичные ключи никогда не должны меняться. Обновление первичного ключа всегда должно быть исключено. Это потому, что он, скорее всего, будет использоваться в нескольких индексах и использоваться в качестве внешнего ключа. Обновление одного первичного ключа может привести к ряду изменений.
  3. НЕ используйте «первичный ключ вашей проблемы» в качестве первичного ключа вашей логической модели. Например, номер паспорта, номер социального страхования или номер контракта сотрудника, поскольку эти «первичные ключи» могут меняться в реальных ситуациях.

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

86 голосов
/ 03 декабря 2008

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

  • Штаты США: я бы выбрал код штата ('TX' для Техаса и т. Д.), А не штатный_ид = 1 для Техаса
  • Сотрудники: я обычно создавал бы искусственный employee_id, потому что трудно найти что-то еще, что работает. SSN или аналогичный может работать, но могут быть проблемы, как у нового столяра, который еще не предоставил свой SSN.
  • История зарплаты сотрудника: (employee_id, start_date). Я бы не создал бы искусственный employee_salary_history_id. Какой точке это послужило бы (кроме «глупой последовательности» )

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

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas
25 голосов
/ 05 декабря 2008

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

Допустим, у нас есть эти таблицы и столбцы:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Если последний бит не имеет смысла, Invoice.CompanyId является частью двух внешних ключей: одного для таблицы CostCentre и одного для таблицы CostElement . Первичный ключ ( InvoiceId , CompanyId ).

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

.

Чем меньше шансов испортить, тем лучше.

20 голосов
/ 13 июля 2011

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

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

13 голосов
/ 03 декабря 2008

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

Для создания суррогатного ключа .

можно использовать столбец Identity (связанный с уникальным индексом в полях-кандидатах).

Это старая дискуссия. Я предпочитаю суррогатные ключи в большинстве ситуаций.

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

RE: РЕДАКТИРОВАТЬ

Да, в этом много споров: D

Я не вижу очевидного преимущества в натуральных ключах, кроме того факта, что они являются естественным выбором. Вы всегда будете думать в Имя, SocialNumber - или что-то в этом роде - вместо idPerson .

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

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

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

11 голосов
/ 03 декабря 2008

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

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

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

8 голосов
/ 03 июня 2013

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

Просто процитирую несколько пунктов:

Разработчик должен применить несколько правил при выборе первичного ключа для каждой таблицы:

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

Естественные ключи (как правило) нарушают правила. Суррогатные ключи соответствуют правилам. (Вам лучше прочитать эту статью, она стоит вашего времени!)

7 голосов
/ 03 января 2013

Что особенного в первичном ключе?

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

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

  • В сторону: к сожалению, побочный эффект большинства разрабатываемых баз данных и разработчики прикладных программ (которые я иногда) то, что лучше всего подходит для приложения или платформы приложения часто управляет выбором первичного ключа для таблиц. Это приводит к целому числу и Ключи GUID (так как они просты в использовании для каркасов приложений) и конструкции монолитных столов (так как они уменьшают количество приложений каркасные объекты, необходимые для представления данных в памяти). Эти Прикладные решения по проектированию баз данных приводят к значительным данным проблемы согласованности при использовании в масштабе. Фреймворки приложений разработанные таким образом, естественно, приводят к столу одновременно. «Частичные записи» создаются в таблицах, а данные заполняются с течением времени. Взаимодействие с несколькими столами избегается или когда используется вызывает противоречивость данные, когда приложение работает неправильно. Эти конструкции ведут к данным, которые не имеют смысла (или трудно понять), распространение данных над таблицами (вы должны смотреть на другие таблицы, чтобы понять смысл текущая таблица) и дублированные данные.

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

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

НаличиеСказав это, я благодарен за многие плохо спроектированные базы данных, которые существуют сегодня на предприятиях (бессмысленные-суррогатные ключи-данные-повреждены-1NF), потому что это означает, что есть бесконечный объем работы для людей, которые понимают правильный дизайн базы данных. Но с грустной стороны, это иногда заставляет меня чувствовать себя как Сизиф, но я держу пари, что у него был один черт 401k (до крушения). Держитесь подальше от блогов и веб-сайтов для важных вопросов дизайна базы данных. Если вы разрабатываете базы данных, посмотрите CJ Date. Вы также можете ссылаться на Celko для SQL Server, но только если сначала будете держать себя за нос. На стороне Oracle, ссылка Тома Кайта.

6 голосов
/ 03 декабря 2008

Естественный ключ, если он доступен, обычно лучше. Итак, если datetime / char однозначно идентифицирует строку и обе части имеют значение для строки, это здорово.

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

5 голосов
/ 03 декабря 2008

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

«Каждый клиент в моей базе данных будет и должен иметь SSN». Бам, готово, сделай его первичным ключом и покончим с этим. Просто помните, когда ваше бизнес-правило меняется, вы сожжены.

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

...