Составные первичные ключи против уникального поля идентификатора объекта - PullRequest
71 голосов
/ 01 октября 2008

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

Обоснование этой конкретной схемы схемы от человека, который ее написал, было связано с тем, как база данных обрабатывает поля идентификаторов неэффективным образом, и когда она строит индексы, сортировки деревьев ошибочны. Этому объяснению не хватало глубины, и я все еще пытаюсь обдумать концепцию (я знаком с использованием составных ключей, но не в 100% случаев).

Может кто-нибудь высказать свое мнение или добавить большую глубину к этой теме?

Ответы [ 15 ]

88 голосов
/ 02 октября 2008

Большинство обычно используемых механизмов (MS SQL Server, Oracle, DB2, MySQL и т. Д.) Не испытывают заметных проблем при использовании системы суррогатных ключей. Некоторые могут даже испытать повышение производительности от использования суррогата, но проблемы с производительностью сильно зависят от платформы.

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

Аргументы для естественных ключей (единственного или составного) обычно включают в себя следующее:

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

2) Они устраняют необходимость в определенных объединениях. Например, если у вас есть клиенты с кодами клиентов и счетами с номерами счетов (оба из которых являются «естественными» ключами), и вы хотите получить все номера счетов для определенного кода клиента, вы можете просто использовать "SELECT InvoiceNumber FROM Invoice WHERE CustomerCode = 'XYZ123'". В классическом подходе с суррогатным ключом SQL будет выглядеть примерно так: "SELECT Invoice.InvoiceNumber FROM Invoice INNER JOIN Customer ON Invoice.CustomerID = Customer.CustomerID WHERE Customer.CustomerCode = 'XYZ123'".

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

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

1) Они позволяют легче изменять атрибуты при изменении бизнес-требований / правил. Это происходит потому, что они позволяют изолировать атрибуты данных в одной таблице. Это в первую очередь проблема для механизмов SQL, которые неэффективно реализуют стандартные конструкции SQL, такие как DOMAIN. Когда атрибут определен оператором DOMAIN, изменения атрибута могут быть выполнены в рамках всей схемы с помощью оператора ALTER DOMAIN. Различные механизмы SQL имеют разные характеристики производительности для изменения домена, а некоторые механизмы SQL вообще не реализуют DOMAINS, поэтому разработчики моделей данных компенсируют эти ситуации, добавляя суррогатные ключи, чтобы улучшить возможность вносить изменения в атрибуты.

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

3) Они работают лучше, чем естественные ключи. Производительность наиболее напрямую зависит от механизма SQL. Одна и та же схема базы данных, реализованная на одном и том же оборудовании с использованием разных механизмов SQL, часто будет иметь резко отличающиеся характеристики производительности из-за механизмов хранения и поиска данных механизмов SQL. Некоторые механизмы SQL близко приближаются к системам с плоскими файлами, где данные фактически сохраняются избыточно, когда один и тот же атрибут, такой как код клиента, появляется в нескольких местах в схеме базы данных. Это избыточное хранилище с помощью механизма SQL может вызвать проблемы с производительностью, когда необходимо внести изменения в данные или схему. Другие механизмы SQL обеспечивают лучшее разделение между моделью данных и системой хранения / извлечения, что позволяет быстрее изменять данные и схему.

4) Суррогатные ключи работают лучше с определенными библиотеками доступа к данным и средами графического интерфейса. Из-за однородного характера большинства конструкций суррогатных ключей (пример: все реляционные ключи являются целыми числами), библиотеки доступа к данным, ORM, и структуры GUI могут работать с информацией, не требуя специальных знаний о данных. Естественные ключи из-за их разнородной природы (разные типы данных, размер и т. Д.) Не работают так же хорошо с автоматизированными или полуавтоматическими наборами инструментов и библиотеками. Для специализированных сценариев, таких как встроенные базы данных SQL, проектирование базы данных с учетом конкретного инструментария может быть приемлемым. В других сценариях базы данных являются корпоративными информационными ресурсами, доступ к которым осуществляется одновременно несколькими платформами, приложениями, системами отчетов и устройствами, и, следовательно, они не функционируют так же хорошо, если они ориентированы на какую-либо конкретную библиотеку или инфраструктуру. Кроме того, базы данных, предназначенные для работы с определенными наборами инструментов, становятся предметом ответственности при выпуске следующего замечательного набора средств.

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

Есть несколько отличных ресурсов, обсуждающих достоинства каждого подхода:

http://www.google.com/search?q=natural+key+surrogate+key

http://www.agiledata.org/essays/keys.html

http://www.informationweek.com/news/software/bi/201806814

32 голосов
/ 01 октября 2008

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

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

22 голосов
/ 01 октября 2008

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

  • если ключ не постоянен, у вас есть проблема с обновлением в будущем, которая может быть довольно сложной

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

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

РЕДАКТИРОВАТЬ: есть еще одна проблема, которая более практична, чем философская. Во многих случаях вы собираетесь как-то найти определенную строку, а затем обновить ее или найти ее снова (или обе). С составными ключами больше данных для отслеживания и больше ограничений в предложении WHERE для повторного поиска или обновления (или удаления). Также возможно, что один из ключевых сегментов мог измениться за это время! С суррогатным ключом всегда остается только одно значение (суррогатный идентификатор), и по определению оно не может измениться, что значительно упрощает ситуацию.

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

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

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

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

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

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

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

каждый раз, когда я создаю таблицу, я должен терять время

  1. идентифицирует его первичный ключ и его физические характеристики (тип, размер)
  2. запомнив эти характеристики каждый раз, когда я хочу сослаться на это в мой код?
  3. объясняя мой выбор ПК другим разработчики в команде?

Мой ответ «нет» на все эти вопросы:

  1. У меня нет времени терять, пытаясь определить «лучший первичный ключ», когда работа со списком лиц.
  2. Я не хочу помнить, что Первичный ключ моей таблицы "computer" строка длиной 64 символа Windows принимает столько символов для имени компьютера?).
  3. Я не хочу объяснять свой выбор другие разработчики, где один из них наконец скажу "Да, человек, но считай, что ты должен управлять компьютеры в разных доменах? Позволяет ли эта строка из 64 символов Вам хранить доменное имя + имя компьютера? ".

Итак, в течение последних пяти лет я работал с очень простым правилом: каждая таблица (назовем ее 'myTable') имеет свое первое поле с именем 'id_MyTable', которое имеет тип uniqueIdentifier. Даже если эта таблица поддерживает отношение «многие ко многим», например таблицу «ComputerUser», где комбинация «id_Computer» и «id_User» образует очень приемлемый первичный ключ, я предпочитаю создайте это поле 'id_ComputerUser' в качестве уникального идентификатора, просто чтобы придерживаться правила.

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

Я не уверен, что мое правило лучшее. Но это очень эффективно!

5 голосов
/ 01 октября 2008

Использование полей «уникальный (объектный) идентификатор» упрощает объединения, но вы должны стремиться к тому, чтобы другой (возможно, составной) ключ оставался уникальным - НЕ ослабляйте ограничения, не равные нулю, и НЕ поддерживайте ограничение уникальности.

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

4 голосов
/ 22 октября 2008

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

3 голосов
/ 01 октября 2008

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

3 голосов
/ 01 октября 2008

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

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

natural pk имеют свой сценарий мотивации и использования и не являются плохой вещью (тм), они просто не ладят с ORM.

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

2 голосов
/ 21 апреля 2010

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

Формат внешних данных может со временем меняться. Например, вы можете подумать, что ISBN книги станет хорошим первичным ключом в таблице книг. В конце концов, ISBN уникальны. Но поскольку эта конкретная книга написана, издательская индустрия в США готовится к серьезным изменениям, поскольку дополнительные цифры добавляются ко всем ISBN. Если бы мы использовали ISBN в качестве первичного ключа в таблице книг, нам пришлось бы обновлять каждую строку, чтобы отразить это изменение. Но тогда у нас будет другая проблема. В базе данных будут другие таблицы, которые ссылаются на строки в таблице книг через первичный ключ. Мы не сможем изменить ключ в таблице книг, если сначала не пройдем и не обновим все эти ссылки. И это будет включать в себя удаление ограничений внешнего ключа, обновление таблиц, обновление таблицы книг и, наконец, восстановление ограничений. В общем, это что-то вроде боли. Проблемы исчезнут, если мы будем использовать нашу собственную внутреннюю ценность в качестве первичного ключа. Никакая третья сторона не может прийти и произвольно сказать нам изменить нашу схему - мы контролируем наше собственное пространство ключей. И если что-то, например, ISBN, нужно изменить, оно может измениться, не затрагивая какие-либо существующие отношения в базе данных. По сути, мы отделили связывание строк от внешнего представления данных в этих строках.

Хотя объяснение довольно книжное, но я думаю, что оно объясняет вещи проще.

...