Выбор между искусственным первичным ключом и естественным ключом для таблицы Products

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

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

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

Есть идеи, на которые я должен обратить внимание?

Ответов (10)

Решение

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

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

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

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

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

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

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

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

Благодаря уникальному ключевому полю Natural две или более строк никогда не могут иметь одинаковые данные.

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

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

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

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

В конце концов, я пошел с автоматически увеличивающимся PK.

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

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

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

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

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

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

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

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

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

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

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

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

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

DECLARE @Key INT

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

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

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

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

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

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

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