Должен ли я иметь специальное поле первичного ключа? - PullRequest
18 голосов
/ 03 октября 2008

Я проектирую небольшую базу данных SQL для использования веб-приложением.

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

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

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

Ответы [ 11 ]

25 голосов
/ 03 октября 2008

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

11 голосов
/ 03 октября 2008

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

6 голосов
/ 03 октября 2008

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

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

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

2 голосов
/ 03 октября 2008

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

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

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

2 голосов
/ 03 октября 2008

Наличие целочисленного первичного ключа всегда хорошо с точки зрения производительности. Все ваши отношения будут намного эффективнее с целочисленным первичным ключом. Например, JOIN будет намного быстрее ( SQL Server ).

Это также позволит вам будущие модификации базы данных. Довольно часто у вас есть уникальное имя столбца только для того, чтобы потом выяснить, что имя у него вовсе не уникальное.

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

2 голосов
/ 03 октября 2008

Да - и, как правило, всегда для каждой таблицы.

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

Это базовая хорошая практика для схем БД.

1 голос
/ 03 октября 2008

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

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

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

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

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

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

1 голос
/ 03 октября 2008

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

Единственное место, где работают естественные ключи, - это таблица кодов, например, таблица, отображающая значение статуса в его описании. Нет никакого смысла давать «Active» первичный ключ 1, «Delay» первичный ключ 2 и т. Д. Когда так же просто дать «Active» первичный ключ «ACT»; «Задержка», «DLY»; «В ожидании», «HLD» и так далее.

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

1 голос
/ 03 октября 2008

Если вы живете в разреженных кругах теоретических математиков (например, С. Дейт в «стране, где есть нули», потому что все значения данных известны и верны), тогда первичные ключи могут быть построенным из компонентов данных, которые идентифицируют идеализированную платоническую сущность, на которую вы ссылаетесь (например, имя + день рождения + место рождения + имена родителей), но в грязном реальном мире "синтетические ключи", которые могут идентифицировать ваш реальный мир сущности в контексте вашей базы данных - гораздо более практичный способ сделать что-либо. (И пустые поля могут быть очень полезны. Возьмите это, люди теории реляционного дизайна!)

0 голосов
/ 01 марта 2016

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

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

...