Идеи дизайна базы данных «ключ / ID», суррогатный ключ, первичный ключ и т. Д. - PullRequest
5 голосов
/ 22 декабря 2009

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

Я всегда предполагал, что ID был моим первичным ключом в таблице, подобной этой:

Users
    ID, Guid
    FirstName, Text
    LastName, Text
    SSN, Int

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

Согласно Википедии, похоже, что ID - это мой суррогатный ключ, а мой первичный ключ может быть SSN + ID? Это правильно? Это плохой дизайн стола?

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

LogEntry
    ID, Guid
    LogEntryID, Int [sql identity field +1 every time]
    LogType, Int
    Message, Text

Ответы [ 7 ]

12 голосов
/ 22 декабря 2009

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

Первичный ключ используется для уникальной и безопасной идентификации любой строки в вашей таблице. Он должен быть стабильным, уникальным и не иметь значения NULL - «искусственный» идентификатор обычно обладает такими свойствами.

Я бы обычно рекомендовал не использовать "натуральные" или реальные данные для первичных ключей - не ДЕЙСТВИТЕЛЬНО ли 150% уверен, что НИКОГДА не изменится ?? Например, швейцарский эквивалент SSN меняется каждый раз, когда женщина выходит замуж (или разводится) - вряд ли идеальный кандидат. И это не гарантировано быть уникальным, либо ......

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

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

7 голосов
/ 22 декабря 2009

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

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

  1. Они в первую очередь там, чтобы обеспечить целостность и согласованность ваших данных! Каждая строка в таблице представляет экземпляр любой сущности, для которой определена таблица, для хранения данных. Нет Суррогатное Ключ, по определение , может когда-либо выполнять эту функцию. Только правильно разработанный натуральный Ключ может сделать это. (Если все, что у вас есть, это суррогатный ключ, вы всегда можете добавить еще одну строку со всеми другими атрибутами, точно идентичными существующей строке, при условии, что вы зададите ей другое значение суррогатного ключа)
  2. Во-вторых, они служат ссылками (указателями) на внешние ключи в других таблицах, которые являются дочерними объектами объекта в таблице с первичным ключом. Естественный ключ (особенно если он составной из нескольких атрибутов) не является хорошим выбором для этой функции, потому что это будет означать, что A) внешние ключи во всех дочерних таблицах также должны быть составными ключами, что делает их очень широкий, что снижает производительность всех операций с ограничениями и соединений SQL. и B) Если значение ключа изменилось в основной таблице, вам потребуется выполнить каскадные обновления для каждой таблицы, где значение было представлено как FK.

Таким образом, ответ прост ... Всегда (где бы вы ни заботились о целостности / согласованности данных) используйте естественный ключ и, при необходимости, используйте оба! Если естественный ключ является составным, длинным или недостаточно стабильным, добавьте альтернативный суррогатный ключ (например, в виде целого числа с автоинкрементом) для использования в качестве целей FK в дочерних таблицах. Но рискуя потерять согласованность данных вашей таблицы, НЕ удаляйте естественный ключ из основной таблицы.

Чтобы прояснить это, давайте приведем пример. Скажем, у вас есть таблица с банковскими счетами ... Естественным ключом может быть номер банковского маршрута и номер счета в банке. Чтобы не использовать этот двойной составной ключ в каждой записи транзакции в таблице транзакций, вы можете решить добавить искусственно сгенерированный суррогатный ключ в таблицу BankAccount, которая является просто целым числом. Но тебе лучше сохранить естественный Ключ! Если у вас нет, если у вас нет также составного натурального ключа, вы можете легко получить две строки в таблице следующим образом:

id  BankRoutingNumber BankAccountNumber   BankBalance
 1     12345678932154   9876543210123       $123.12
 2     12345678932154   9876543210123    ($3,291.62)

Теперь, какой из них прав?

Как следует из комментариев ниже, что хорошего в том, чтобы вы могли "идентифицировать строку " ?? Мне кажется, что это бесполезно, потому что нам нужно определить, какой банковский счет представляет строка! Идентификация строки важна только для внутренних технических функций базы данных, таких как объединения в запросах, или для операций ограничения FK, которые, если / когда они необходимы, должны в любом случае использовать суррогатный ключ, а не естественный ключ ,

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

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

4 голосов
/ 22 декабря 2009

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

Например, предположим, что у меня была таблица адресов электронной почты для списка рассылки. Я бы хотел, чтобы они были уникальными, верно? Нет смысла иметь 2, 3 или n записей одного и того же адреса электронной почты. Если я использую email_address в качестве своего первичного ключа (который является естественным ключом - он существует в виде данных независимо от созданной вами структуры базы данных), это гарантирует, что у меня никогда не будет дублированного адреса электронной почты в моем списке рассылки.

Однако, если у меня есть поле с именем id в качестве суррогатного ключа, тогда у меня может быть любое количество повторяющихся адресов электронной почты. Это становится плохим, если существует 10 строк с одним и тем же адресом электронной почты, и все они с конфликтующей информацией о подписке в других столбцах. Какой из них правильный, если есть? Там нет никакого способа сказать! После этого ваша целостность данных нарушается. Нет никакого способа исправить данные, кроме как просмотреть записи один за другим, спросив людей, какая информация о подписке действительно верна и т. Д.

Причина, по которой непуристы хотят этого, заключается в том, что он упрощает использование стандартизированного кода, поскольку вы можете рассчитывать на ссылку на одну строку базы данных с целочисленным значением. Если у вас есть естественный ключ, скажем, набора ( client_id, email, category_id ), программист будет ненавидеть кодирование вокруг этого экземпляра! Это как бы нарушает инкапсуляцию кодирования на основе классов, поскольку требует от программиста глубоких знаний о структуре таблиц, а метод удаления может иметь разный код для каждой таблицы. Тьфу!

Так что, очевидно, этот пример слишком упрощен, но он иллюстрирует суть.

3 голосов
/ 22 декабря 2009

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

В SQL Server суррогатный ключ обычно представляет собой значение идентификатора с автоприращением, которое SQL Server генерирует для вас. Он НЕ имеет никакого отношения к фактическим данным, хранящимся в таблице. Противоположностью этому является естественный ключ. Примером может быть номер социального страхования. Это имеет отношение к данным, хранящимся в таблице. Естественные ключи имеют свои преимущества, но, IMO, преимущества использования суррогатных ключей перевешивают естественные ключи.

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

Randy

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

Таблица пользователей

Использование Guid в качестве первичного ключа для таблицы Users: perfect .

Таблица LogEntry

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

0 голосов
/ 22 декабря 2009

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

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

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

В вашем случае я думаю, что LogEntryID для ваших элементов журнала кажется разумным. Является ли идентификатор FK для таблицы Users? Если нет, то я мог бы спросить, есть ли ID и LogEntryID в одной таблице, поскольку они являются избыточными. Если это так, то я бы изменил имя на user_id или что-то подобное.

0 голосов
/ 22 декабря 2009
  • Первичный ключ - это то, что вы делаете. То, что вы определяете как первичный ключ, является первичным ключом. Обычно это поле целочисленного идентификатора.
  • Суррогатным ключом также является это поле идентификатора. Это суррогат естественного ключа, который определяет уникальность с точки зрения данных вашего приложения.

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

Тем не менее, некоторые люди клянутся, просто используя естественный ключ.

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