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

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

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

Ответы

Ответ 1

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

Рассмотрим две таблицы Person и Event, а между ними - отношения "многие ко многим", называемые Appointment.

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

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

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, вам нужно только два поля в таблице Appointment, чтобы определить отношение, а условие намного меньше:

select Person,*, Event.*
from Person, Event, Appointment
where
  Person.Id = Appointment.PersonId and Event.Id = Appointment.EventId

Ответ 2

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

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

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

Наиболее распространенным использованием составного первичного ключа является таблица ссылок "многие ко многим".

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

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

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

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

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

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

Ответ 5

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

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

Person
FirstName
LastName
Адрес

Класс
ИмяКласса
InstructorFirstName
InstructorLastName
InstructorAddress
MeetingTime

StudentClass - множество ссылок на множество StudentFirstName
StudentLastName
StudentAddress
ИмяКласса
InstructorFirstName
InstructorLastName
InstructorAddress
MeetingTime

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

Ответ 6

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

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

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

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

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

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

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

Ответ 7

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

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

Ответ 8

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

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

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

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

Ответ 9

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

Рассмотрим общий пример таблицы с более чем одним ключом-кандидатом: таблица Payroll с столбцами employee_number, salary_amount, start_date и end_date.

Четыре возможных ключа:

UNIQUE (employee_number, start_date); -- simple constraint 
UNIQUE (employee_number, end_date); -- simple constraint 
UNIQUE (employee_number, start_date, end_date); -- simple constraint 
CHECK (
       NOT EXISTS (
                   SELECT Calendar.day_date
                     FROM Calendar, Payroll AS P1
                    WHERE P1.start_date <= Calendar.day_date
                          AND Calendar.day_date < P1.end_date 
                    GROUP 
                       BY P1.employee_number, Calendar.day_date
                 )
      ); -- sequenced key i.e. no over-lapping periods for the same employee

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