Как лучше всего использовать первичные ключи в таблицах?

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

  1. Целочисленный столбец идентификатора, который увеличивается автоматически.
  2. Уникальный идентификатор (GUID)
  3. Столбец с коротким символом (x) или целым числом (или другим относительно небольшим числовым типом), который может служить столбцом идентификатора строки.

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

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

Вопрос :-)

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

  • дата и время / символ
  • дата и время / целое число
  • datetime / varchar
  • char / nvarchar / nvarchar

Есть ли для этого веские основания? Я бы всегда определял столбец идентификатора или уникального идентификатора для этих случаев.

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

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

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

Я нашел Навыки базы данных: разумный подход к выбору первичных ключей хорошим чтением и следую большинству изложенных пунктов.

user2864740 21.11.2013 05:03
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
267
1
163 412
21
Перейти к ответу Данный вопрос помечен как решенный

Ответы 21

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

Кстати, GUID в качестве первичного ключа может снизить производительность. Я бы не рекомендовал это.

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

JC. 03.12.2008 18:50

"Преждевременная оптимизация" - это зацикленная фраза на ТАК (ИМХО)! Да, GUID могут потребоваться в НЕКОТОРЫХ случаях, но Эндрю прав, указывая на то, что они не должны использоваться в качестве типа данных по умолчанию, независимо от того, требуются они или нет.

Tony Andrews 03.12.2008 19:01

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

JC. 03.12.2008 20:05

Или используйте оба. Имейте первичный ключ на основе int / long для удобного быстрого выбора и объединения, а затем укажите поле guid. По крайней мере, это то, что я делаю. Это неправильно? Разве я не должен этого делать? :)

Andrew Rollings 03.12.2008 20:09

Я тоже использую обе колонки. Но не уверен, неправильно это или нет. Ты нашел его @AndrewRollings?

Yogi 22.03.2020 13:40

Таблицы всегда должны иметь первичный ключ. Когда это не так, это должны быть поля AutoIncrement.

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

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

Я согласен. И в случае, когда нужно вставить много данных, удалите ограничение первичного ключа (или используйте INSERT IDENTITY ON в TSQL) и затем верните его обратно :)

Andrew Rollings 03.12.2008 18:35

Есть исключения: очевидно, связаны таблицы

annakata 03.12.2008 18:36

Другая причина: если нет PK / уникального ключа, браузеры таблиц (я имею в виду, что-то вроде Access / SQL Server Management Studio) откажутся обновлять / удалять одну строку с дублированной строкой. Для этого вам придется написать SQL.

Dennis C 03.12.2008 19:10

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

David Aldridge 03.12.2008 22:36

Естественный ключ, если он доступен, обычно лучше. Итак, если datetime / char однозначно идентифицирует строку, и обе части значимы для строки, это прекрасно.

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

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

JC. 03.12.2008 18:56

ВСЕГДА должен быть естественный ключ для любой строки в вашей базе данных. Этот «естественный» ключ может быть чем-то сгенерирован в деловом мире или вашей технической системой, но он должен существовать всегда.

Tom H 03.12.2008 19:29

Итак, вы называете столбец guid PK естественным ключом?

JC. 03.12.2008 19:45

Если в вашем мире это единственный способ идентифицировать строку в таблице, тогда да. Конечно, когда дизайнер решает создать GUID для PK, обычно это происходит потому, что они не проделали работу по поиску НАСТОЯЩЕГО естественного ключа, поэтому в этом случае GUID НЕ является естественным ключом.

Tom H 03.12.2008 19:53

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

James Orr 03.12.2008 22:23

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

James Orr 03.12.2008 22:24

@Barry: RE: # 2. если естественный мир меняется, и это приводит к изменению вашего естественного ключа, это означает, что вы плохо справились с выбором естественного ключа. По определению естественный ключ не меняется со временем.

Tom H 03.12.2008 22:45

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

Tom H 03.12.2008 23:18

@TomH. Их сложность в выборе правильно звучит как удар по ним. Люди на этой странице предложили как SSN, так и Last name в качестве возможных естественных ключей.

Sqeaky 09.05.2012 00:27

@TomH Ты серьезно? «ВСЕГДА должен быть естественный ключ для любой строки в вашей базе данных.», Когда у меня есть элементы накладной для накладной?

Betlista 02.12.2018 01:14

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

Tom H 03.12.2018 17:26

Вы должны использовать «составной» или «составной» первичный ключ, состоящий из нескольких полей.

Это вполне приемлемое решение, перейдите по здесь для получения дополнительной информации :)

Я тоже всегда использую столбец числового идентификатора. В оракуле я использую число (18,0) без реальной причины выше числа (12,0) (или любого другого типа int, а не long), может быть, я просто не хочу беспокоиться о том, чтобы получить несколько миллиардов строк в дб!

Я также включаю созданный и измененный столбец (тип timestamp) для базового отслеживания, где это кажется полезным.

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

Я также должен отметить, что я не помещаю идентификаторы в таблицы ссылок / соединений, а только в таблицы, содержащие данные.

JeeBee 03.12.2008 18:41

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

Эта стратегия разваливается, когда вам теперь нужно пройти по 6 таблицам, чтобы объединить две необходимые вам таблицы, потому что составные ключи не были распространены. Это также приводит к необходимости использования циклов / курсоров для нескольких вставок, что может быть ОГРОМНЫМ падением производительности.

Tom H 03.12.2008 19:32

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

Dan Blair 08.12.2008 07:23

Я всегда использую автономный номер или поле идентификации.

Я работал с клиентом, который использовал SSN в качестве первичного ключа, а затем из-за правил HIPAA был вынужден перейти на «MemberID», что вызвало массу проблем при обновлении внешних ключей в связанных таблицах. Соблюдение единого стандарта столбца идентичности помогло мне избежать подобной проблемы во всех моих проектах.

Плохой выбор естественного ключа разработчиком не означает, что естественные ключи плохие.

Tom H 03.12.2008 19:30

Инструмент, которым сложно пользоваться, почему-то не является аргументом против этого инструмента?

Sqeaky 09.05.2012 00:34

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

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

Это старая дискуссия. Я предпочитаю суррогатные ключи в большинстве ситуаций.

Но отсутствию ключа нет оправдания.

RE: РЕДАКТИРОВАТЬ

Да, по этому поводу много споров: D

Я не вижу очевидных преимуществ естественных ключей, кроме того факта, что они являются естественным выбором. Вы всегда будете думать в Имя, SocialNumber - или что-то в этом роде - вместо idPerson.

Суррогатные ключи - это ответ на некоторые проблемы, с которыми сталкиваются естественные ключи (например, распространение изменений).

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

Но в конце концов вы обнаружите, что это всего лишь вопрос вкуса или мышления. Люди «думают лучше» с естественными ключами, а другие - нет.

Люди «думают лучше» с естественными ключами. Машины и базы данных - нет.

F.D.Castel 07.01.2009 00:26

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

  • Штаты США: я бы выбрал state_code (TX для Техаса и т. д.), А не state_id = 1 для Техаса.
  • Сотрудники: Обычно я создаю искусственный идентификатор employee_id, потому что трудно найти что-то еще, что работает. SSN или эквивалент могут работать, но могут возникнуть проблемы, например, с новым участником, который еще не предоставил свой SSN.
  • История зарплат сотрудников: (employee_id, start_date). Я бы нет создал искусственный employee_salary_history_id. Какой смысл это будет (кроме "глупая последовательность")

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

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas

В некоторых случаях с SQL server 2005/2008 естественный (текстовый) ключ может быть быстрее, чем ключ int. У меня есть приложение с дружественным кодом из 7-8 символов, который мы используем в качестве первичного ключа, и это было быстрее (и часто удобнее), чем суррогат int. В любом случае нам нужен код, чтобы иметь удобочитаемый / запоминающийся код, который мы могли бы безопасно передать без конфликта в другой экземпляр приложения (несколько сайтов, которые объединяются в более крупный сайт).

lambacck 30.05.2011 18:46

+1 Хороший ответ. Тем не менее, я бы сделал сотрудника по кадрам надежным источником идентификатора сотрудника, то есть сотрудником, ответственным за проверку сотрудников в реальной жизни, которые, вероятно, будут использовать идентификаторы, такие как SSN, принимать ссылки и т. д. Отделу персонала следует доверять источник идентификаторов сотрудников, а не СУБД!

onedaywhen 26.01.2012 20:27

@ onedaywhen- Я бы не стал. доверяйте кадровику. Люди уходят, приходят новые и имеют разные идеи. Предоставьте им доступ к идентификатору, который, по их мнению, является уникальным / они хотят использовать, но внутренне для db, dba должны принимать собственное решение.

Dave Pile 17.04.2017 10:04

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

maja 05.09.2017 09:22

Также в некоторых странах (я думаю, даже в США) они действительно рекомендуют не сообщать SSN.

Stijn de Witt 13.10.2017 22:37

Да, для личной информации лучше иметь искусственный идентификатор, который нельзя связать с естественным идентификатором. Например, SSN должен быть только для внутреннего использования, никогда не отображаться при обмене данными и т. д. (Даже в зашифрованном виде в базе данных!). Я помню, когда мой колледж в США использовал SSN в качестве номера счета ... Затем мне пришлось изменить его из-за проблем с PII.

ps2goat 19.04.2019 20:17

В США при определенных обстоятельствах ваш SSN может МЕНЯТЬСЯ !!! Они также используются повторно.

Evvo 12.04.2020 17:21

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

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

Если вы действительно хотите прочитать всю эту многовековую дискуссию, поищите «естественный ключ» в Stack Overflow. Вы должны вернуться на страницы с результатами.

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

Я соблюдаю несколько правил:

  1. Первичные ключи должны быть настолько малы, насколько это необходимо. Предпочитайте числовой тип, потому что числовые типы хранятся в гораздо более компактном формате, чем символьные форматы. Это связано с тем, что большинство первичных ключей будут внешними ключами в другой таблице, а также будут использоваться в нескольких индексах. Чем меньше ваш ключ, тем меньше индекс, тем меньше страниц в кеше вы будете использовать.
  2. Первичные ключи никогда не должны меняться. Об обновлении первичного ключа не может быть и речи. Это связано с тем, что он, скорее всего, будет использоваться в нескольких индексах и использоваться в качестве внешнего ключа. Обновление одного первичного ключа может вызвать волновой эффект изменений.
  3. НЕ используйте «первичный ключ проблемы» в качестве первичного ключа логической модели. Например, номер паспорта, номер социального страхования или номер контракта сотрудника в качестве «первичного ключа» может измениться в реальных ситуациях.

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

Мне это нравится! У вас есть какая-то документация, в которой основаны ваши "правила"? Спасибо!

Lloyd Cotten 03.12.2008 23:13

Нет, просто опыт. При работе с «маленькими» базами данных это не имеет большого значения. Но когда вы имеете дело с большими БД, все мелочи имеют значение. Только представьте, если у вас есть 1 миллиард строк с int или long pk по сравнению с использованием text или guid. Разница огромная!

Logicalmind 03.12.2008 23:31

Просто не забудьте поместить этот уникальный индекс на естественный ключ (если он действительно существует, что часто не так), когда вы используете искусственный ключ.

HLGEM 10.12.2008 01:54

@Lloyd Cotten: Вот что говорит поставщик механизма больших данных в поддержку правила номер 1: skyfoundry.com/forum/topic/24. Это убедило меня вернуться к Int.

hobs 21.03.2013 01:57

даже если вы «знаете», что «естественный ключ мал и никогда не изменится», подумайте дважды. «Мы никогда не используем эти коды повторно» - знаменитые последние слова…. Единственные вещи, которые попадают в категорию небольших, никогда не меняющихся, - это стандарты ISO и другие стандарты (коды стран, коды аэропортов iata). Такие вещи, как «каково двухбуквенное представление этого внутреннего бренда» ... дважды подумайте, прежде чем предположить, что «это» никогда не изменится, вы на расстоянии одного финансового решения от восстановления базы данных.

Andrew Hill 11.09.2015 05:04

Просто чтобы добавить к пункту 3 ... естественный ключ также может быть непубличными данными, и, как правило, ключи на стороне клиента select / option или input hidden точно такие же, как и в вашей таблице ... в этом В этом случае для генерации временных ключей на стороне клиента может потребоваться некоторая обработка, которой можно избежать - наряду с проблемой безопасности данных - с помощью суррогатных ключей.

Felypp Oliveira 16.12.2015 04:07

Номер паспорта может измениться. Страны могут обанкротиться. Форматы даты могут меняться (календари менялись за всю историю). Многие ситуации в реальном мире могут измениться, но что плохого в использовании естественного ключа для чего-то, что, как вы ЗНАЕТЕ, не изменит?

Zvi Twersky 20.12.2016 17:03

Для меня естественные и искусственные ключи - это вопрос того, сколько бизнес-логики вы хотите использовать в своей базе данных. ИНН (SSN) - отличный пример.

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

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

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

HLGEM 10.12.2008 01:48

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

Zvi Twersky 20.12.2016 17:15

Я ищу естественные первичные ключи и использую их, где могу.

Если естественные ключи не могут быть найдены, я предпочитаю GUID, а не INT ++, потому что SQL Server использует деревья, а всегда добавлять ключи в конец деревьев - это плохо.

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

Поскольку мне посчастливилось использовать SQL Server, я могу изучать планы выполнения и статистику с помощью профилировщика и анализатора запросов и очень легко узнавать, как работают мои ключи.

Есть ли у вас документация, подтверждающая это утверждение: «если естественные ключи не могут быть найдены, я предпочитаю GUID, а не INT ++, потому что SQL Server использует деревья, а всегда добавлять ключи в конец деревьев - плохо». Не скептически, просто пытаюсь собрать какую-то документацию.

Lloyd Cotten 03.12.2008 22:45

@Lloyd - Рад, что ты проявляешь интерес к чему-то, что меня очень увлекает. Хорошая отправная точка в msdn.microsoft.com/en-us/library/ms177443(SQL.90).aspx

Guge 03.12.2008 22:52

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

Вам необходимо создать COMB GUID. Хорошая статья об этом и статистика производительности Стоимость GUID в качестве первичных ключей.

Также некоторый код для создания COMB GUID в SQL находится в Уникальный идентификатор против идентичности (архив).

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

Logicalmind 03.12.2008 22:58

Если вы перейдете по ссылке, которую я предоставил выше, разница в производительности при использовании COMB Guids очень небольшая.

Donny V. 04.12.2008 19:58

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

Допустим, у нас есть эти таблицы и столбцы:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Если последний бит не имеет смысла, Invoice.CompanyId является частью двух внешних ключей, одного для таблицы CostCentre и одного для таблицы CostElement. Первичный ключ - (InvoiceId, Идентификатор компании).

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

Чем меньше шансов облажаться, тем лучше.

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

Samuel Danielson 31.03.2010 07:11

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

  • Идентификатор строки (GUID)
  • Создатель (строка; по умолчанию используется имя текущего пользователя (SUSER_SNAME() в T-SQL))
  • Создано (DateTime)
  • Отметка времени

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

Между тем, настоящий ПК, если возможно, является естественным ключом. Мои внутренние правила выглядят примерно так:

  • Люди - используйте суррогатный ключ, например ИНТ. Если он внутренний, приемлемым выбором будет GUID пользователя Active Directory.
  • Таблицы поиска (например, StatusCodes) - используйте короткий код CHAR; его легче запомнить, чем INT, и во многих случаях бумажные формы и пользователи также будут использовать его для краткости (например, Status = «E» для «Просрочено», «A» для «Утверждено», «NADIS» для «Асбест не обнаружен. В образце »)
  • Связывание таблиц - комбинация FK (например, EventId, AttendeeId)

Таким образом, в идеале вы получите естественный, понятный и запоминающийся ПК и удобный для ORM GUID с одним идентификатором для каждой таблицы.

Предостережение: базы данных, которые я поддерживаю, имеют тенденцию к 100 000 записей, а не к миллионам или миллиардам, поэтому, если у вас есть опыт работы с более крупными системами, который противоречит моему совету, не стесняйтесь игнорировать меня!

Вы предлагаете создать обе SK GUIDиINT для таблиц без сильного естественного ключа?

user565869 04.05.2012 21:35

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

Keith Williams 09.05.2012 11:27

Я избегаю использования естественных ключей по одной простой причине - человеческая ошибка. Хотя естественные уникальные идентификаторы часто доступны (SSN, VIN, номер счета и т. д.), Для их правильного ввода требуется человек. Если вы используете SSN в качестве первичного ключа, кто-то заменяет пару чисел во время ввода данных, и ошибка не обнаруживается сразу, тогда вам придется изменить свой первичный ключ.

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

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

Alex Jorgenson 25.02.2013 00:16

Что особенного в первичном ключе?

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

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

  • В стороне: к сожалению, побочный эффект большинства разрабатываемых баз данных и разработан прикладными программистами (которыми я иногда являюсь) что то, что лучше всего подходит для приложения или фреймворка приложения, часто управляет выбором первичного ключа для таблиц. Это приводит к целому и Ключи GUID (так как они просты в использовании для фреймворков приложений) и монолитные конструкции столов (так как они сокращают количество приложений объекты инфраструктуры, необходимые для представления данных в памяти). Эти решения по проектированию базы данных, основанные на приложениях, приводят к значительным данным проблемы согласованности при использовании в большом масштабе. Фреймворки приложений спроектированные таким образом, естественно, приводят к созданию таблиц за раз. «Частичные записи» создаются в таблицах, и данные заполняются с течением времени. Взаимодействие с несколькими таблицами избегается или при использовании вызывает несогласованность данные, когда приложение работает некорректно. Эти конструкции приводят к данным, которые не имеют смысла (или трудны для понимания), данные распространяются над таблицами (вам нужно посмотреть на другие таблицы, чтобы понять текущая таблица) и дублированные данные.

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

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

Сказав это, я благодарен за множество плохо спроектированных баз данных, которые существуют сегодня на предприятиях (чудовища с бессмысленным суррогатным ключом-данными-поврежденными-1NF), потому что это означает, что людям, которые понимают, как правильно проектировать базы данных, предстоит бесконечный объем работы. . Но, к сожалению, иногда это заставляет меня чувствовать себя Сизифом, но держу пари, что у него было чертовски 401k (до крушения). Держитесь подальше от блогов и веб-сайтов по важным вопросам проектирования баз данных. Если вы разрабатываете базы данных, найдите CJ Date. Вы также можете сослаться на Celko для SQL Server, но только если сначала зажмете нос. Со стороны Oracle ссылка на Тома Кайта.

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

Waz 07.03.2013 06:58

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

Rodney P. Barbati 20.01.2021 20:23

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

Процитирую несколько моментов:

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

  • Первичный ключ должен однозначно идентифицировать каждую запись.
  • Значение первичного ключа записи не может быть нулевым.
  • Первичная пара "ключ-значение" должна существовать при создании записи.
  • Первичный ключ должен оставаться стабильным - вы не можете изменять поля первичного ключа.
  • Первичный ключ должен быть компактным и содержать минимально возможное количество атрибутов.
  • Значение первичного ключа изменить нельзя.

Естественные ключи (как правило) нарушают правила. Суррогатные ключи соответствуют правилам. (Вам лучше прочитать эту статью, она того стоит!)

Вы сказали - первичный ключ-значение должен существовать при создании записи. Я бы сказал, что для любого нового объекта, который вы создаете, PK не будет существовать, пока он не будет создан во время INSERT. Это предполагает, что вы используете некоторую форму программно сгенерированного первичного ключа, который я бы порекомендовал. Если вы сообразительны, вы можете использовать этот факт для выполнения UPSERT, а не INSERT или UPDATE.

Rodney P. Barbati 20.01.2021 20:27

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

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

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

Наличие первичного ключа с одним значением делает выполнение UPSERT очень простым.

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

  • Если ваши таблицы большие, попробуйте разбить таблицу на сегменты на основе наиболее важных критериев поиска.

  • Если у вас есть таблица со значительным количеством полей Id, рассмотрите возможность удаления всех, кроме первичного ключа, в одну таблицу, которая имеет идентификатор (PK), org_id (FK для исходной таблицы) и столбец id_type. Создайте индексы для всех столбцов в новой таблице и свяжите ее с исходной таблицей. Таким образом, теперь вы можете выполнять индексированный поиск любого количества идентификаторов, используя только один индекс.

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