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

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

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

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

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

Ответ 1

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

Ответ 2

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

Ответ 3

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

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

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

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

Ответ 7

Если вы живете в разреженных кругах теоретических математиков (например, C. Date in the-land-where-there-are-no-nulls, потому что все значения данных известны и правильны), тогда первичные ключи могут быть построены из компонентов данных, которые идентифицируют идеализированную платоническую сущность, к которой вы обращаетесь (например, имя + день рождения + место рождения + родительские имена), но в беспорядочном реальном мире "синтетические ключи", которые могут идентифицировать ваш реальный мир объекты в контексте вашей базы данных - гораздо более практичный способ сделать что-то. (И поля с нулевым значением могут быть очень полезны. Возьмите это, люди теории реляционной теории!)

Ответ 8

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

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

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

Ответ 9

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

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

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

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

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

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

Ответ 10

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

Ответ 11

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

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