Нужно ли каждой таблице использовать автоматически увеличивающий искусственный первичный ключ?
Почти каждая таблица в каждой базе данных, которую я видел за 7 лет опыта разработки, имеет автоматически увеличивающий первичный ключ. Почему это? Если у меня есть таблица в штатах США, где каждое состояние, в котором каждое государство должно иметь уникальное имя, используется использование автоматически увеличивающего первичный ключ? Почему бы просто не использовать имя состояния в качестве первичного ключа? Мне кажется оправданием, позволяющим дубликаты, замаскированные под уникальные строки.
Это кажется мне очевидным, но опять же, никто другой, кажется, не приходит и не действует на тот же логический вывод, что и я, поэтому я должен предположить, что у меня есть хороший шанс, я ошибаюсь.
Есть ли какая-то реальная практическая причина, по которой нам нужно использовать автоинкрементные клавиши?
Ответы
Ответ 1
Нет.
В большинстве случаев наличие суррогатного ключа INT IDENTITY
- это простой вариант: он может быть гарантированно НЕ НАЧАЛЬНЫМ и 100% уникальным, что-то много "натуральных" ключей не предлагает - имена могут меняться, поэтому могут SSN и другие элементы информации.
В случае сокращений и названий состояний - во всяком случае, я бы использовал двухбуквенную аббревиатуру состояния как ключ.
Первичный ключ должен быть:
- уникальный (гарантированный 100%! Не только "почти" уникальный)
- NON NULL
Первичный ключ должен быть:
- стабильно, если вообще возможно (не изменяется - или, по крайней мере, не слишком часто)
Двухбуквенные коды состояния определенно предложили бы это - это может быть кандидат на естественный ключ. Ключ также должен быть небольшим - INT из 4 байтов является идеальным, двухбуквенный столбец CHAR (2) тот же. Я бы не использовал поле VARCHAR (100) или что-то подобное в качестве ключа - он просто слишком неуклюжий, скорее всего, будет меняться все время - не хороший кандидат.
Таким образом, хотя вам не нужно иметь автоматически увеличивающийся "искусственный" (суррогатный) первичный ключ, это часто довольно хороший выбор, поскольку никакие естественные данные на самом деле не являются задачей первичного ключа и вы хотите избежать огромных первичных ключей с несколькими столбцами - они слишком неуклюжи и неэффективны.
Ответ 2
Этот вопрос неоднократно задавался на SO и был предметом много дискуссий на протяжении многих лет среди (и между) разработчиков и администраторов баз данных.
Позвольте мне начать с того, что предпосылка вашего вопроса подразумевает, что один подход универсально превосходит другой... это редко бывает в реальной жизни. Суррогатные ключи и естественные ключи имеют свои возможности и проблемы - и важно понять, что они собой представляют. Какой бы выбор вы ни выбрали в своей системе, имейте в виду, что есть преимущество в последовательности - это упрощает понимание модели данных и упрощает разработку запросов и приложений. Я также хочу сказать, что я предпочитаю суррогатные ключи над натуральными ключами для ПК... но это не означает, что естественные ключи иногда не могут быть полезны в этой роли.
Важно понимать, что суррогатные и естественные ключи НЕ являются взаимоисключающими - и во многих случаях они могут дополнять друг друга. Имейте в виду, что "ключ" для таблицы базы данных - это просто то, что уникально идентифицирует запись (строку). Вполне возможно, что одна строка имеет несколько ключей, представляющих различные категории ограничений, которые делают запись уникальной.
Первичный ключ, с другой стороны, является особым уникальным ключом, который база данных будет использовать для обеспечения ссылочной целостности и представления внешнего ключа в других таблицах. Для любой таблицы может быть только один первичный ключ. существенное качество первичного ключа заключается в том, что оно на 100% уникально и не равно NULL. желаемое качество первичного ключа состоит в том, что оно является стабильным (неизменным). Хотя возможны изменяемые первичные ключи, они вызывают много проблем для базы данных, которые лучше избегать (каскадные обновления, сбои RI и т.д.). Если вы решите использовать суррогатный первичный ключ для своих таблиц, вы также должны рассмотреть возможность создания уникальных ограничений, чтобы отразить существование каких-либо естественных ключей.
Суррогатные ключи полезны в случаях, когда:
- Натуральные ключи нестабильны (значения могут меняться со временем)
- Натуральные ключи большие или громоздкие (несколько столбцов или длинные значения)
- Естественные ключи могут меняться со временем (столбцы добавляются/удаляются со временем)
Предоставляя короткое, стабильное, уникальное значение для каждой строки, мы можем уменьшить размер базы данных, повысить ее производительность и снизить волатильность зависимых таблиц, в которых хранятся внешние ключи. преимущество ключевого polymorphism, о котором я расскажу позже.
В некоторых случаях использование естественных ключей для выражения связей между таблицами может быть проблематичным. Например, представьте, что у вас есть таблица PERSON, чей естественный ключ был {LAST_NAME, FIRST_NAME, SSN}
. Что произойдет, если у вас есть еще одна таблица GRANT_PROPOSAL, в которой вам нужно сохранить ссылку на Proposer, Reviewer, Approver и Authorizer. Теперь вам нужно 12 столбцов, чтобы выразить эту информацию. Вам также нужно придумать какое-либо соглашение об именах, чтобы определить, какие столбцы принадлежат тому или иному лицу. Но что, если для вашей таблицы PERSON требуется 6 или 8 или 24 столбца для естественного ключа? Это быстро становится неуправляемым. Суррогатные ключи разрешают такие проблемы, разводя семантику (значение) ключа от его использования в качестве идентификатора.
Давайте также рассмотрим пример, который вы описали в своем вопросе.
Если в качестве первичного ключа этой таблицы используется двухзначное аббревиатура состояния.
На поверхности, похоже, поле аббревиатуры удовлетворяет требованиям хорошего первичного ключа. Он относительно короткий, его легко распространять как внешний ключ, он выглядит стабильным. К сожалению, вы не контролируете набор сокращений... почтовая служба. И вот интересный факт: в 1973 году USPS изменил аббревиатуру Небраски от NB до NE, чтобы свести к минимуму путаницу с Нью-Брансуиком, Канада. Мораль истории состоит в том, что естественные ключи часто находятся вне контроля базы данных... и они могут меняться со временем. Даже если вы думаете, что они не могут. Эта проблема еще более выражена для более сложных данных, таких как люди или продукты и т.д. По мере развития бизнеса, определения того, что делает такие сущности уникальными, могут измениться. И это может создать значительные проблемы для разработчиков данных и разработчиков приложений.
Раньше я упоминал, что первичные ключи могут поддерживать ключевой полиморфизм. Что это значит? Ну, полиморфизм - это способность одного типа, A, появляться как и использоваться как другой тип, B. В базах данных эта концепция относится к способности сочетать ключи от разных классов сущностей в одну таблицу. Давайте посмотрим на пример. Представьте себе, что вы хотите иметь контрольную цепочку в своей системе, которая идентифицирует, какие объекты были изменены, каким пользователем в какой день. Было бы неплохо создать таблицу с полями: {ENTITY_ID, USER_ID, EDIT_DATE}
. К сожалению, используя естественные ключи, разные объекты имеют разные ключи. Итак, теперь нам нужно создать отдельную таблицу привязки для каждого типа сущности... и создать наше приложение таким образом, чтобы он понимал разные типы сущностей и как их ключи имеют форму.
Не поймите меня неправильно. Я не сторонник того, что ключи суррогата должны ВСЕГДА использоваться. В реальном мире никогда, никогда и не всегда опасно позиционировать. Один из самых больших недостатков суррогатных ключей заключается в том, что они могут приводить к таблицам, которые имеют внешние ключи, состоящие из множества "бессмысленных" чисел. Это может затруднить интерпретацию значения записи, поскольку для получения полной картины вам необходимо присоединиться или найти записи из других таблиц. Это также может усложнить развертывание распределенной базы данных, поскольку присвоение уникальных инкрементных номеров для серверов не всегда возможно (хотя большинство современных баз данных, таких как Oracle и SQLServer, смягчают это посредством репликации последовательности).
Ответ 3
Я думаю, что использование слова "Первичный" во фразе "Первичный" Ключ в реальном смысле, вводит в заблуждение.
Сначала используйте определение, что "ключ" является атрибутом или набором атрибутов, которые должны быть уникальными в таблице,
Затем, если любой ключ служит нескольким часто взаимно непоследовательным целям.
Цель 1. Использовать в качестве условий объединения одну или несколько записей в дочерних таблицах, которые имеют отношение к этой родительской таблице. (Явное или неявное определение внешнего ключа в этих дочерних таблицах)
Цель 2. (связанное) Обеспечение того, чтобы дочерние записи должны иметь родительскую запись в родительской таблице (дочерняя таблица FK должна существовать как ключ в родительской таблице)
Цель 3. Чтобы повысить производительность запросов, которым необходимо быстро найти определенную запись/строку в таблице.
Цель 4. ( Наиболее важно с точки зрения согласованности данных!). Чтобы обеспечить согласованность данных, предотвращая включение повторяющихся строк, которые представляют собой один и тот же логический объект, itno table. (Это часто называют "естественным" ключом и должно состоять из атрибутов таблицы (сущности), которые относительно инвариантны.)
Очевидно, что любой незначительный, неестественный ключ (например, GUID или автоматически генерируемое целое число полностью, неспособный удовлетворить Цель 4.
Но часто, со многими (наиболее) таблицами, вполне естественный ключ, который может обеспечить # 4, часто будет состоять из нескольких атрибутов и быть слишком широким или настолько широким, чтобы использовать его для целей # 1, # 2 или # 3 приведет к неприемлемым последствиям производительности.
Ответ прост. Используйте оба варианта. Используйте простой автоматический генератор интегрального ключа для всех Joins и FK в других дочерних таблицах, но убедитесь, что для каждой таблицы, для которой требуется согласованность данных (в очень немногих таблицах нет), есть альтернативный естественный уникальный ключ, который предотвратит вставку несогласованных строк данных... Плюс, если у вас всегда есть оба, то все возражения против использования естественного ключа (что, если он изменится? Я должен изменить каждое место, на которое он ссылается, как FK) становится спорным, поскольку вы не используете его для этого... Вы используете его только в одной таблице, где это ПК, чтобы избежать непоследовательных дублирующих данных...
Единственный раз, когда вы можете обойтись без них, - это полностью автономная таблица, которая не участвует в каких-либо отношениях с другими таблицами и имеет очевидный и надежный естественный ключ.
Ответ 4
Как правило, числовой первичный ключ будет работать лучше, чем строка. Вы можете дополнительно создать уникальные ключи, чтобы предотвратить дублирование дубликатов. Таким образом, вы получаете уверенность в отсутствии дубликатов, но вы также получаете производительность чисел (против строк в вашем сценарии).
Во всех вероятностях основные базы данных имеют некоторые оптимизации производительности для целых первичных ключей, которые отсутствуют для первичных ключей на основе строк. Но это только разумное предположение.
Ответ 5
Да, на мой взгляд, каждая таблица нуждается в автоматическом добавочном целочисленном ключе, потому что это делает JOIN и (особенно) интерфейсное программирование намного, намного, намного проще. Другие считают по-другому, но это более чем 20-летний опыт работы.
Единственное исключение - небольшие таблицы "code" или "lookup", в которых я готов заменить короткое (4 или 5 символов) значение кода TEXT. Я делаю это, потому что я часто использую многие из них в своих базах данных, и это позволяет мне представить значимый экран пользователю без необходимости искать описание в таблице поиска или присоединять его к набору результатов. Ваш пример таблицы States будет соответствовать этой категории.
Ответ 6
Нет, абсолютно нет.
Наличие первичного ключа, который не может измениться, является хорошей идеей (UPDATE является законным для столбцов первичного ключа, но в целом потенциально запутанным и может создавать проблемы для дочерних строк). Но если ваше приложение имеет какой-то другой кандидат, который более подходит, чем значение с автоматическим приращением, то вы, вероятно, должны его использовать.
Производительность, в целом, меньше столбцов лучше и, особенно, меньше индексов. Если у вас есть другой столбец с уникальным индексом и никогда не может быть изменен никаким бизнес-процессом, он может быть подходящим первичным ключом.
Говоря с точки зрения MySQL (Innodb), также неплохо использовать "реальный" столбец как первичный ключ, а не "искусственный", поскольку InnoDB всегда кластеризует первичный ключ и включает его во вторичные индексы ( вот как он находит в них строки). Это дает возможность сделать полезную оптимизацию с помощью первичного ключа, который он не может использовать с каким-либо другим уникальным индексом. Пользователи MSSQL часто предпочитают группировать первичный ключ, но он также может группировать уникальный уникальный индекс.
EDIT:
Но если это небольшая база данных, и вы не слишком заботитесь о производительности или размере, добавление ненужного столбца автоинкремент не так уж плохо.
Неавтоматически увеличивающееся значение (например, UUID или какая-либо другая строка, сгенерированная в соответствии с вашим собственным алгоритмом) может быть полезна для распределенных, оштукатуренных или разнообразных систем, где сохранение согласованного автоинкрементного ID затруднено (или невозможно - думаю распределенной системы, которая продолжает вставлять строки с обеих сторон сетевого раздела).
Ответ 7
Я думаю, что есть две вещи, которые могут объяснить причину, по которой иногда используются автоматически увеличивающиеся ключи:
-
Космическое рассмотрение; ok ваше имя штата не много, но пространство, которое он занимает, может сложить. Если вы действительно хотите сохранить состояние с его именем в качестве первичного ключа, тогда продолжайте, но это займет больше места. Это может быть не проблема в некоторых случаях, и это звучит как проблема старины, но привычка, возможно, укоренилась. И мы, программисты и администраторы баз данных, любим привычки: D
-
Оборонительное соображение: у меня недавно была следующая проблема; у нас есть пользователи в базе данных, где электронное письмо является ключом ко всей идентификации. Почему бы не сделать по электронной почте обещающий ключ? за исключением того, что внезапные пограничные случаи ползут в том месте, где один парень должен быть там дважды, чтобы иметь два разных адреса, и никто не говорил об этом в спецификациях, поэтому адрес не нормализуется, и там такая ситуация, когда два разных письма должны указывать на одного и того же человека... Через некоторое время вы перестанете вытягивать свои волосы и добавьте столбец id целых чисел
Я не говорю, что это плохая привычка, ни хорошая; я уверен, что хорошие системы могут быть разработаны вокруг разумных первичных ключей, но эти два момента заставляют меня полагать, что страх и привычка являются двумя среди виновных
Ответ 8
Это ключевой компонент реляционных баз данных. Наличие целого числа связано с состоянием вместо того, чтобы иметь полное имя состояния, сохраняет кучу места в вашей базе данных! Представьте, что у вас есть миллион записей, ссылающихся на вашу таблицу состояний. Вы хотите использовать 4 байта для числа в каждой из этих записей или хотите использовать весь crapload байтов для каждого имени состояния?
Ответ 9
Вот некоторые практические соображения.
Большинство современных ORM (рельсы, django, hibernate и т.д.) работают лучше всего, когда в качестве первичного ключа есть единственный целочисленный столбец.
Кроме того, наличие стандартного соглашения об именах (например, id как первичный ключ и table_name_id для внешних ключей) облегчает идентификацию ключей.