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

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

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

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

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

одно обычно встречается исключение для «системных» данных. т.е. вещи, которые вы определяете сами, поля статуса и т.д.

ShoeLace 03.10.2008 17:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
18
1
4 242
11
Перейти к ответу Данный вопрос помечен как решенный

Ответы 11

Ответ принят как подходящий

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

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

Ken Ray 03.10.2008 17:18

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

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

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

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

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

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

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

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

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

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

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

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

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

Darrel Miller 03.10.2008 17:40

О, когда это случится, нам всем станет плохо!

Jeffrey L Whitledge 03.10.2008 20:46

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

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

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

Другой пример: country_code (US, UK и т. д.). Люди склонны использовать 4-байтовый INT, тогда как CHAR(2) CHARACTER SET ascii занимает всего 2 байта и работает лучше по другим причинам. Когда Чехословакия разделится на Чехию и Словакию, вам придется писать код для любого дизайна первичного ключа.

Rick James 09.06.2017 02:21

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

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

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

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

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

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

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

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

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

Обратите внимание, что снижение производительности за вставку в родительскую и дочернюю таблицы необходимо только в том случае, если вы настаиваете на создании родительского, затем дочернего, затем родительского, затем дочернего. Просто сначала создайте 1K родителей, а затем 5K детей.

user565869 20.04.2012 02:00

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

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

Другие вопросы по теме