Подтвердить что ты не робот

Композитный первичный ключ

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

В качестве примера рассмотрим следующую таблицу, которая иллюстрирует проблему:

----------------------------------------------------------------
| source_id | id_on_source | data                              |
----------------------------------------------------------------
| 1         | 17600        | ...                               |
| 1         | 17601        | ...                               |
| 2         | 1            | ...                               |
| 3         | 1            | ...                               |
----------------------------------------------------------------

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

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

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

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

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

4b9b3361

Ответ 1

Я лично считаю составные первичные ключи болезненными. Для каждой таблицы, к которой вы хотите присоединиться к таблице "Источники", вам нужно добавить поле source_id и id_on_source.

Я бы создал стандартный автоматически увеличивающий первичный ключ в вашей таблице источников и добавил уникальный индекс в столбцы source_id и id_on_source.

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

Как правило, я также нашел поддержку составных первичных ключей во многих средах и инструментах, которые в лучшем случае были "неоднородными" и вообще отсутствовали в других

Ответ 2

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

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

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

Ответ 3

У вас есть бизнес-требование, что комбинация этих двух атрибутов уникальна. Таким образом, для этих двух атрибутов должно быть ограничение UNIQUE. Вызываете ли вы, что ограничение UNIQUE "primary" действительно просто предпочтение, оно не имеет большого влияния, кроме документации.

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

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

Ответ 4

Я считаю, что составные клавиши создают очень естественную и описательную модель данных. Мой опыт исходит от Oracle, и я не думаю, что при создании составной ПК возникают технические проблемы. Фактически, любой, кто анализирует словарь данных, сразу поймет что-то о таблице. В вашем случае было бы очевидно, что каждый источник_ид должен иметь уникальный id_on_source.

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

Ответ 5

В значительной степени единственный раз, когда я использую составной первичный ключ, является то, что старшая часть ключа является ключом к другой таблице. Например, я мог бы создать таблицу OrderLineItem с первичным ключом OrderId + LineNumber. Поскольку многие обращения к таблице OrderLineItem будут "упорядочивать последовательность orderlineitem с использованием (orderid)" или некоторые варианты этого, это часто бывает удобно. Это также облегчает просмотр дампов базы данных, чтобы выяснить, какие позиции связаны с каким порядком.

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

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

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

Ответ 6

У меня возникли проблемы с использованием множества составных клавиш, поэтому я бы не рекомендовал его (более подробно), я также обнаружил, что преимущества в независимом/суррогатном ключе (а не естественном) при попытке опрокинуть обратные ошибки пользователя. Проблема заключалась в том, что через набор отношений одна таблица объединила две таблицы, где для каждой части строки составной была одинаковой (это было уместно в 3-й нормальной форме - сравнение между двумя частями родителя). Я де-дублировал эту часть составных отношений в таблице соединений (поэтому вместо parent1ID, other1ID, parent2ID, other2ID был parentID, other1ID, other2ID), но теперь отношение не могло обновлять изменения в первичном ключе, поскольку оно пыталось сделать это дважды через каждый маршрут и провалиться посередине.

Ответ 7

Некоторые люди рекомендуют использовать глобально уникальный идентификатор (GUID): репликация слиянием и репликация транзакций с обновлением подписки используют столбцы uniqueidentifier, чтобы гарантировать уникальность идентификаторов строк через несколько копий таблицы. Если значение, если оно уникально, когда оно создано, то вам не нужно добавлять source_id, чтобы сделать его уникальным.


Хотя uniqueid является хорошим первичным ключом, я согласен, что обычно лучше использовать другой, естественный (не обязательно уникальный) ключ в качестве вашего кластерного индекса. Например, если uniqueid является PK, который идентифицирует сотрудников, вы можете захотеть, чтобы кластеризованный индекс был отделом (если ваши операторы выбора обычно извлекают всех сотрудников в рамках данного отдела). Если вы хотите использовать unqiqueid в качестве кластерного индекса, см. Функцию NEWSEQUENTIALID(): это создает последовательные уникальные значения, которые (будучи последовательными ) имеют лучшую производительность кластеризации.

Ответ 8

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

Используя этот дополнительный столбец идентификатора в качестве внешнего ключа в других ссылочных таблицах, вместо ключа, который представляет себя естественным образом, вам придется делать БОЛЬШЕ объединений, а именно во всех случаях, когда вам нужен оригинальный soruce_ID plus ID_on_source вдоль с данными из таблицы ссылок.