Должен ли я использовать составные первичные ключи или нет? - PullRequest
17 голосов
/ 08 июня 2009

Кажется, что есть только поддержка второго класса для составных ключей базы данных в JPA Java (через аннотации EmbeddedId или IdClass). И когда я читаю составные ключи, независимо от языка, люди продолжают сталкиваться с тем, что они - плохая вещь. Но я не могу понять почему. Можно ли использовать композитные ключи в наши дни? Если нет, то почему нет?

Я нашел одного человека, который согласен со мной: http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx

Но другой, кто этого не делает: http://weblogs.java.net/blog/bleonard/archive/2006/11/using_composite.html

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

Простой пример:

Actor { Id, Name, Email } Movie { Id, Name, Year } Character { Id, Name } Role { Actor, Movie, Character }

Здесь Актер, Кино и Персонаж, очевидно, выигрывают от наличия столбца Id в качестве основного ключа.

Но Роль - это таблица соединения «многие ко многим». Я не вижу смысла в создании идентификатора просто для идентификации строки в базе данных. Мне кажется очевидным, что первичный ключ - { Actor, Movie, Character }. Это также кажется довольно ограничивающим свойством, особенно если данные в таблице соединений все время меняются, вы можете столкнуться с коллизиями первичного ключа, как только последовательность первичных ключей обернется до 0.

Итак, возвращаясь к первоначальному вопросу, все еще приемлема практика использования составных первичных ключей? Если нет, то почему нет?

Ответы [ 10 ]

14 голосов
/ 08 июня 2009

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

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

  2. Единообразие: если каждая таблица имеет уникальный числовой идентификатор, и вы также поддерживаете какой-то стандарт в отношении ее имени (например, «ID» или «tablename_id»), код и SQL, ссылающиеся на нее, более понятны (в моем мнение).

Есть и другие причины, но это только несколько.

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

Надеюсь, это поможет.

10 голосов
/ 08 июня 2009

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

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

То же самое с БД, если ПК составной, это реальность, поэтому модель должна быть чистой и ясной. Композитный ПК более понятен, чем автоинкремент + ограничение + микс. Когда вы видите столбец ID, который ничего не делает, вам нужно спросить, что такое настоящий PK, есть ли какие-то другие скрытые вещи, о которых вам следует знать, и т. Д. Чистый PK не оставляет никаких сомнений.

БД - это основа вашего приложения, для меня нам нужна самая надежная основа, которую мы можем иметь. На этой основе мы создадим приложение (веб или нет). Так что я не могу понять, почему мы должны сгибать модель БД, чтобы она соответствовала некоторым конкретным инструментам / фреймворку / языку разработки. Данные направляют приложение, а не наоборот. Что если ORM изменится в будущем и станет устаревшим, и появится лучшее решение, навязывающее другую модель? Мы не можем играть с моделью db, чтобы соответствовать той или иной структуре, модель должна оставаться прежней, она не должна зависеть от того, какой инструмент мы используем для доступа к данным ...

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

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

6 голосов
/ 08 июня 2009

Аналогичные вопросы были заданы по SO, и нет единого мнения;)

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

Чтобы обернуть последовательность, вам понадобится 2 миллиарда записей в одной таблице (32 бита) или 10 ^ 18 с 64-битными пакетами.

Кстати, ваша модель данных не допускает персонажей фильма с неизвестными актерами.

5 голосов
/ 09 июня 2009

Религиозные войны были и продолжаются по этому вопросу.

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

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

То, как вы хотите получить ответ на свой вопрос, зависит только от того, какую религию вы предпочитаете. Моя личная религия - Data. Эта религия доказала свою способность выживать в любой шумихе и тенденциях с 1969 года.

5 голосов
/ 08 июня 2009

Мое общее мнение ... нет. не используйте составные первичные ключи.

Они, как правило, усложняют ORM, если вы их используете (ORM иногда заходят настолько далеко, что называют составные первичные ключи «устаревшим поведением»), и, как правило, если вы используете несколько ключей, один или несколько из них будут скорее естественными чем технические ключи, что для меня является более серьезной проблемой: ИМХО вам, безусловно, следует отдать предпочтение техническим первичным ключам.

Подробнее об этом в Ошибки при разработке баз данных, сделанные AppDevelopers .

3 голосов
/ 08 июня 2009

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

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

2 голосов
/ 08 июня 2009

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

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

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

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

2 голосов
/ 08 июня 2009

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

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

Итак: я бы использовал составные первичные ключи.

1 голос
/ 19 августа 2010

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

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

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

1 голос
/ 08 июня 2009

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

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

...