Выбор между искусственным первичным ключом и естественным ключом для таблицы продуктов - PullRequest
20 голосов
/ 26 февраля 2009

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

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

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

Есть идеи, на которые мне стоит взглянуть?

Ответы [ 10 ]

43 голосов
/ 26 февраля 2009

Это выбор между суррогатными и естественными первичными ключами .

ИМХО всегда в пользу суррогатных первичных ключей. Первичные ключи не должны иметь значения, потому что это значение может измениться. Даже названия стран могут измениться, и страны могут появиться и исчезнуть, не говоря уже о продуктах. Изменение первичных ключей определенно не рекомендуется, что может произойти с естественными ключами.

Подробнее о суррогатных и первичных ключах :

Значит, суррогатные ключи выигрывают, верно? Что ж, давайте рассмотрим и посмотрим, есть ли к естественным ключам относятся к суррогатные ключи:

  • Con 1: Размер первичного ключа - суррогатные ключи обычно не имеют проблем с размером индекса, так как они обычно один столбец типа int. Это примерно такой маленький, как может.
  • Con 2: Размер внешнего ключа - у них нет внешнего ключа или внешнего ключа проблемы размера индекса либо для та же причина, что и у Con 1.
  • Con 3: Астетика - ну, это глаз типа вещи смотрящего, но они, конечно, не связаны с написанием столько же кода, сколько с составным натуральным ключи.
  • Con 4 & 5: Опциональность и применимость - суррогатные ключи не имеют проблемы с людьми или вещами нет желая или не имея возможности предоставить данные.
  • Con 6: Уникальность - они на 100% гарантированно уникальны. Это рельеф.
  • Con 7: Конфиденциальность - у них нет проблем с конфиденциальностью, если недобросовестный человек их получает.
  • Con 8: Случайная денормализация - Вы не можете случайно денормализовать некоммерческие данные.
  • Con 9: Каскадные обновления - суррогатные ключи не меняются, поэтому нет беспокоится о том, как их каскадировать обновить.
  • Con 10: Скорость соединения Varchar - обычно они целые, поэтому они обычно присоединиться так быстро, как только сможете.

И есть также Суррогатные ключи против естественных ключей для первичного ключа?

10 голосов
/ 03 февраля 2010

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

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

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

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

DECLARE @Key INT

UPDATE  KeyTable
WITH    (rowlock)
SET @Key = LastKey = LastKey + 1
WHERE   KeyType = 'Product'

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

Почему следует избегать буквенно-цифровых первичных ключей:

Три основные проблемы: производительность, сопоставление и пространство.

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

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

Пробел - 9-символьный SKU, такой как у David, занимает девять байт, а целое - только четыре (2 для smallint, 1 для tinyint). Даже bigint занимает всего 8 байтов.

4 голосов
/ 26 февраля 2009

Когда-либо существующая опасность с естественными ключами заключается в том, что либо ваши первоначальные предположения будут ошибочны сейчас или в будущем, когда будут сделаны какие-то изменения вне вашего контроля, либо в каком-то месте вам нужно будет сослаться на запись, где передается значимое поле не является обязательным (например, веб-приложение, которое использует номер социального страхования сотрудника в качестве первичного ключа, а затем должно использовать URL-адреса, такие как /employee.php?ssn=xxxxxxx)

Исходя из моего личного опыта использования "уникальных" SKU и каналов поставщиков - вы абсолютно уверены они посылают вам фид с полными, уникальными, правильно сформированными SKU?

Мне приходилось лично сталкиваться со всеми перечисленными ниже фактами при получении каналов от поставщиков, которые имеют различные уровни ИТ и технической компетенции:

  • В товарах отсутствует SKU полностью ("")
  • Клерки использовали SKU-заполнители в своей базе данных, такие как 999999999 и 00000000, и никогда не исправляли их
  • Те, кто вводит или импортирует данные, путают между различными номерами продуктов, смешивают такие вещи, как UPC и SCC, или даже находят способы их объединить (я видел коды SCC с невозможными контрольными цифрами в конце, потому что они просто скопировал UPC и добавил 01 или 10, не исправляя контрольную цифру)
  • По особым причинам или просто из-за некомпетентности поставщик ввел один и тот же продукт дважды в свою базу данных (например, версии 1 и 2 версии одной и той же материнской платы имеют одинаковый SKU, но существуют в виде 2 записей в базе данных поставщиков). и подача данных, потому что версия 2. имеет новые функции)
2 голосов
/ 26 февраля 2009

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

1 голос
/ 10 апреля 2013

Суррогатный ключ (поле INT с автоматическим приращением) однозначно идентифицирует строку в таблице. С другой стороны, уникальный природный ключ (productName) предотвратит попадание дубликатов данных о продукте в таблицу.

С уникальным полем Natural key две или более строки не могут иметь одинаковые данные.

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

Давайте возьмем пример таблицы User, поле Natural key таблицы (userName) не позволит одному и тому же пользователю зарегистрироваться дважды, а поле INT с автоматическим приращением (userId) - нет.

1 голос
/ 26 февраля 2009

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

1 голос
/ 26 февраля 2009

Очень похоже на мой вопрос несколько месяцев назад ...

Должен ли я иметь специальное поле первичного ключа?

Я пошел с автоматическим увеличением PK в конце.

1 голос
/ 26 февраля 2009

Я бы посоветовал иметь автоинкрементное "бессмысленное" целое число в качестве первичного ключа. Если кому-то придет в голову идея реорганизации идентификаторов продуктов, по крайней мере, ваша БД не будет иметь проблем.

0 голосов
/ 26 февраля 2009

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

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

0 голосов
/ 26 февраля 2009

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

...