Почему я читаю так много негативных мнений об использовании составных ключей?

После того, как я недавно столкнулся с той же проблемой, я придумал следующее решение:

Сначала найдите все ItemTags, где tagName либо «смешно», либо «политика» и возвращает массив ItemTag _ids.

Затем найдите элементы, которые содержат все ItemTag _ids в массиве тегов

ItemTag
  .find({ tagName : { $in : ['funny','politics'] } })
  .lean()
  .distinct('_id')
  .exec((err, itemTagIds) => {
     if (err) { console.error(err); }
     Item.find({ tag: { $all: itemTagIds} }, (err, items) => {
        console.log(items); // Items filtered by tagName
     });
  });
13
задан Jeff 18 August 2010 в 13:59
поделиться

8 ответов

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

Рассмотрим две таблицы Person и Event , а также отношения «многие ко многим» между ними, называемые Назначение .

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

Условие для привязки отношения будет довольно длинным:

select Person,*, Event.*
from Person, Event, Appointment
where
  Person.FirstName = Appointment.PersonFirstName and
  Person.LastName = Appointment.PersonLastName and
  Person.BirthDate = Appointment.PersonBirthDate and
  Event.Place = Appointment.EventPlace and
  Event.Name = Appointment.EventName`.

Если у вас, с другой стороны, есть ключи с автоматической нумерацией для таблиц Person и Event , вам нужно только два поля в таблице Назначение для определения отношения, а условие намного меньше:

select Person,*, Event.*
from Person, Event, Appointment
where
  Person.Id = Appointment.PersonId and Event.Id = Appointment.EventId
12
ответ дан 1 December 2019 в 19:30
поделиться

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

https://stackoverflow.com/search?q=composite+primary+key

1
ответ дан 1 December 2019 в 19:30
поделиться

Если вы используете только чистый самописный SQL для доступа к своим данным, с ними все в порядке.

Однако некоторые ORM , адаптеры и т. Д. Требуют наличия единственного поля PK для идентификации записи.

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

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

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

Это не так в вашем случае.

Во-первых, человек может изменить свое имя и даже дату рождения

Во-вторых, я легко могу представить себе двух Джонов Смита , родившихся в один день.

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

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

7
ответ дан 1 December 2019 в 19:30
поделиться

Если ваша РСУБД поддерживает их и если вы используете их правильно (и последовательно), уникальных ключей на составном PK должно быть достаточно, чтобы избежать дубликатов. По крайней мере, в SQL Server вы также можете создавать FK по уникальному ключу вместо PK, что может быть полезно.

Преимущество единственного столбца "id" (или суррогатного ключа) в том, что он может повысить производительность за счет более узкого ключа. Поскольку этот ключ может быть перенесен в индексы этой таблицы (как указатель на физическую строку из индексной строки) и в другие таблицы как FK-столбец, это может уменьшить пространство и улучшить производительность. Однако многое зависит от конкретной архитектуры вашей РСУБД. К сожалению, я недостаточно знаком с Access, чтобы прокомментировать это.

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

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

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

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

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

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

3
ответ дан 1 December 2019 в 19:30
поделиться

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

Вот простой пример, использующий типичное расположение ученика / класса.

Человек
Имя
Фамилия
Адрес

Класс
ClassName
InstructorFirstName
InstructorLastName
Адрес инструктора
MeetingTime

StudentClass - таблица объединения "многие ко многим"
StudentFirstName
StudentLastName
StudentAddress
ClassName
InstructorFirstName
InstructorLastName
Инструктор Адрес
MeetingTime

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

3
ответ дан 1 December 2019 в 19:30
поделиться

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

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

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

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

1
ответ дан 1 December 2019 в 19:30
поделиться

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

  1. Я использую суррогатный ключ только тогда, когда нет единственного столбца кандидата-ключа. Это означает, что у меня есть таблицы с суррогатными PK и с естественными PK с одним столбцом, но нет составных ключей (за исключением соединений, где они являются составом двух FK, суррогатных или естественных ключей не имеет значения).

  2. Кластеры Jet / ACE на ПК и только на ПК. Это имеет потенциальные недостатки и потенциальные преимущества (например, если вы рассматриваете случайный Autonumber как PK).

  3. По моему опыту, требование ненулевого значения для составного PK делает большинство естественных ключей невозможными без использования потенциально проблемных значений по умолчанию. Это также разрушает ваш уникальный индекс в Jet / ACE, поэтому в приложении Access (до 2010 года) вы в конечном итоге обеспечиваете уникальность в своем приложении.Начиная с A2010, макросы данных на уровне таблиц (которые работают как триггеры), вероятно, могут использоваться для переноса этой логики в ядро ​​базы данных.

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

  5. Как я упоминал выше, единственные составные ключи в моих приложениях находятся в таблицах соединения N: N. Я бы никогда не добавил суррогатный ключ в таблицу соединения , за исключением в относительно редком случае, когда таблица соединения сама является родительской для связанных таблиц (например, запись Person / Company N: N могла иметь связанные JobTitles , т. е. несколько рабочих мест в одной компании). Вместо того, чтобы хранить составной ключ в дочерней таблице, вы бы сохранили суррогатный ключ. Скорее всего, я бы не стал делать суррогатный ключ PK - я бы оставил составной PK на паре значений FK. Я бы просто добавил Autonumber с уникальным индексом для присоединения к дочерним таблицам.

Я буду добавлять больше, когда думаю об этом.

3
ответ дан 1 December 2019 в 19:30
поделиться

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

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

4
ответ дан 1 December 2019 в 19:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: