Почему один первичный ключ лучше, чем составной ключ? - PullRequest
20 голосов
/ 19 апреля 2010

Почему отказ от составных ключей в пользу всех таблиц, использующих один первичный ключ с именем id? Потому что, как правило, все ORM следуют этому.

EDIT

Я только начал изучать ruby ​​на рельсах, и в книге agile development by pragmatic есть строка: --- Rails действительно не работают слишком хорошо, если в каждой таблице нет числового первичного ключа. Менее суетливое название колонки. Такую же строчку я прочитал, когда изучал Учение.

EDIT2 Пожалуйста, проверьте эту ссылку тоже. Я все больше и больше путаюсь с этой вещью: --- Составные первичные ключи и поле уникального идентификатора объекта

Из приведенной выше ссылки: -

* первичный ключ должен быть постоянным и бессмысленным; несуррогатные ключи обычно не соответствуют одному или обоим требованиям, в конечном итоге

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

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

РЕДАКТИРОВАТЬ: есть еще одна проблема, которая более практична, чем философская. Во многих случаях вы собираетесь как-то найти определенную строку, а затем обновить ее или найти ее снова (или обе). С составными ключами, есть больше данных для отслеживания и больше ограничений в предложении WHERE для повторного поиска или обновления (или удаления). Также возможно, что один из ключевых сегментов мог измениться за это время! С суррогатным ключом всегда остается только одно значение (суррогатный идентификатор), и по определению оно не может измениться, что значительно упрощает ситуацию. *

Ответы [ 9 ]

23 голосов
/ 19 апреля 2010

Я не думаю, что есть общее утверждение, что вам следует использовать только один первичный ключ с именем id.

Большинство людей используют суррогатный первичный ключ в качестве автоматической генерации int, потому что он изолирует первичный ключ от необходимости когда-либо менять его, например, если вы сделаете PK именем пользователя, а затем они изменили свое официальное имя. Вы должны обновить PK и все столбцы FK, чтобы отразить новое имя. если вы использовали суррогатный первичный ключ, вы просто обновляете имя пользователя в одном месте (потому что таблицы объединяются в int, а не в имени).

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

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

13 голосов
/ 19 апреля 2010

Единственное реальное ограничение, с которым я столкнулся при использовании составных ключей, касается использования выражения IN с подзапросом. Это проблема, потому что подзапрос в выражении IN должен возвращать один столбец (по крайней мере, в T-SQL).

SELECT
    emp.Name,
    emp.UserDomain,
    emp.UserID
FROM
    employee emp
WHERE
    ???? IN (SELECT e.UserDomain, e.UserID FROM ... /* some complex 
                                                       non-correlated subquery 
                                                       or CTE */
            )

Конечно, всегда есть обходные пути, но иногда это может раздражать.

Это едва ли причина избегать составного ключа в местах, где его целесообразно использовать.

8 голосов
/ 19 апреля 2010

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

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

5 голосов
/ 19 апреля 2010

Что ж, в основном речь идет о простоте JOINs, которую проще понять:

SELECT
   p.ID, p.Name, p.City,
   c.ID, c.Country, c.ISOCode
FROM
   dbo.Parent p
INNER JOIN
   dbo.Child c on c.ParentID = p.ID

или

SELECT
   p.ID, p.Name, p.City,
   c.ID, c.Country, c.ISOCode
FROM
   dbo.Parent p
INNER JOIN
   dbo.Child c ON c.ParentName = p.Name
     AND c.ParentCity = p.City
     AND c.ParentCountry = p.Country

Если у вас есть составные первичные ключи, любой, кто присоединяется к вашей таблице из дочерней таблицы, должен «перетащить» все эти столбцы, и все эти столбцы также будут присутствовать в дочерней таблице, а операторы JOIN довольно беспорядочные. Намного лучше иметь единственный (даже суррогатный) ключ для JOIN!

3 голосов
/ 19 апреля 2010

Я работал над приложением с первичным ключом из 11 столбцов. Всегда было очень весело перепечатывать список снова и снова, каждый раз, когда я хотел гарантировать, что обновляю одну строку. Это был драйвер ошибок, MS-Access не мог справиться с более чем 10 столбцами в ПК и т. Д.

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

2 голосов
/ 20 апреля 2010

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

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

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

1 голос
/ 19 апреля 2010
  1. Для ORM один идентификатор столбец с постоянным именем, как table_id проще, чем составной ключ. Но каждая хорошая поддержка ORM составные ключи.

  2. Простой ПК может быть легко «автоинкрементно» базой данных. Это не относится к составному ключ.

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

Это не значит, что простые PK лучше, чем составные.

0 голосов
/ 19 апреля 2010

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

Традиционная теория реляционных баз данных имела дело в основном с "естественными" ключами (те, которые имеют значение с точки зрения бизнес-сферы), и в этом сценарии часто встречаются составные ключи ... естественно.

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

0 голосов
/ 19 апреля 2010

Объекты в ОО-программировании имеют идентичность независимо от их содержимого. Строки (кортежи) в реляционных базах данных идентифицируются только по их содержанию. Таким образом, когда вы действительно выполняете ORM, т.е. отображаете объекты из объектно-ориентированного языка программирования в реляционную базу данных, необходимо предоставить дополнительный идентификатор, отличный от полей и / или свойств, которые объект имеет в программе - если только один или несколько из них как-то известно, чтобы идентифицировать объекты однозначно.

...