Я хочу знать, является ли составные первичные ключи плохой практикой, а если нет, то какие сценарии рекомендуется использовать.
Мой вопрос основан на этой статье
Часть о составных первичных ключах:
Плохая практика № 6: составные первичные ключи
Это своего рода спорный момент, поскольку многие разработчики баз данных в настоящее время говорят об использовании автоматически сгенерированного поля с целочисленным идентификатором в качестве первичного ключа вместо составного, определяемого комбинацией двух или более полей. В настоящее время это определяется как «наилучшая практика», и лично я склонен согласиться с этим.
Однако это всего лишь соглашение, и, конечно, DBE позволяют определять составные первичные ключи, что многие дизайнеры считают неизбежным. Следовательно, как и в случае избыточности, составные первичные ключи являются проектным решением.
Однако следует помнить, что если ваша таблица с составным первичным ключом будет иметь миллионы строк, индекс, управляющий составным ключом, может вырасти до такой степени, что производительность операции CRUD сильно снизится. В этом случае гораздо лучше использовать простой первичный ключ с целочисленным идентификатором, индекс которого будет достаточно компактным, и установить необходимые ограничения DBE для поддержания уникальности.
источник
Ответы:
Сказать, что использование
"Composite keys as PRIMARY KEY is bad practice"
это полная ерунда!Композиты
PRIMARY KEY
часто являются очень «хорошей вещью» и единственным способом моделирования естественных ситуаций, возникающих в повседневной жизни!Подумайте о классическом учебном примере Базы данных-101 для студентов и курсов, а также о многих курсах, которые посещают многие студенты!
Создать таблицы курса и ученика:
Я приведу пример на диалекте PostgreSQL (и MySQL ) - должен работать на любом сервере с небольшим количеством настроек.
Теперь, вы , очевидно , хотите , чтобы отслеживать, какой студент принимает какой курс - так у вас есть то , что называется
joining table
(также называемойlinking
,many-to-many
илиm-to-n
таблица). Они также известны какassociative entities
на более техническом жаргоне!1 курс может иметь много студентов.
1 студент может пройти много курсов.
Итак, вы создаете объединяющий стол
Теперь, единственный способ разумно придать этому столу
PRIMARY KEY
- сделатьKEY
это комбинацией курса и ученика. Таким образом, вы не можете получить:дубликат студента и комбинации курса
на курс может быть зачислен один и тот же студент один раз, и
студент может записаться на один и тот же курс только один раз
у вас также есть готовый поиск
KEY
по курсу для каждого студента - AKA индекс покрытия ,тривиально найти курсы без студентов и студентов, которые не посещают курсы!
- В примере db-fiddle ограничение PK свернуто в CREATE TABLE - Это можно сделать любым способом. Я предпочитаю иметь все в выражении CREATE TABLE.
Теперь вы могли бы, если обнаружили, что поиск ученика по курсу был медленным, использовать
UNIQUE INDEX
on (sc_student_id, sc_course_id).Там нет нет серебряной пули для добавления индексов - они будут делать
INSERT
с иUPDATE
S медленнее, но на большой выгоду чрезвычайно убывающиеSELECT
раз! Разработчик должен решить индексировать, учитывая их знания и опыт, но говорить, что составныеPRIMARY KEY
s всегда плохи, просто неправильно.В случае объединения таблиц они обычно являются единственными,
PRIMARY KEY
которые имеют смысл! Присоединение к столам также очень часто является единственным способом моделирования того, что происходит в бизнесе или на природе, или практически во всех сферах, которые я могу придумать!Этот ПК также используется в качестве
covering index
ускорения поиска. В этом случае было бы особенно полезно, если бы кто-то регулярно проводил поиск (course_id, student_id), что, как можно себе представить, часто имело бы место!Это всего лишь небольшой пример того, как композит
PRIMARY KEY
может быть очень хорошей идеей и единственным разумным способом моделирования реальности! Сверху головы я могу думать о многом другом.Пример из моей собственной работы!
Рассмотрим таблицу полетов, содержащую flight_id, список аэропортов вылета и прилета и соответствующее время, а также таблицу cab_crew с членами экипажа!
Только разумный способ это может быть смоделировано, чтобы иметь таблицу flight_crew с flight_id и crew_id как и атрибуты объявления единственными разумным
PRIMARY KEY
, чтобы использовать составной ключ из двух полей!источник
id
первичный ключ и уникальный индексcs_student_id
cs_course_id
и иметь те же результаты?Мой полуобразованный подход: «первичный ключ» не должен быть единственным уникальным ключом, используемым для поиска данных в таблице, хотя инструменты управления данными предложат его в качестве выбора по умолчанию. Таким образом, для выбора, использовать ли в качестве ключа таблицы составной файл из двух столбцов или случайное (возможно, последовательное) число, вы можете иметь два разных ключа одновременно.
Если значения данных включают подходящий уникальный термин, который может представлять строку, я бы лучше объявил это как «первичный ключ», даже если он составной, чем использовал бы «синтетический» ключ. Синтетический ключ может работать лучше по техническим причинам, но мой собственный выбор по умолчанию состоит в том, чтобы назначить и использовать реальный термин в качестве первичного ключа, если только вам действительно не нужно идти другим путем, чтобы ваша служба работала.
Microsoft SQL Server имеет отличительную, но связанную особенность «кластеризованного индекса», который управляет физическим хранением данных в порядке индекса, а также используется внутри других индексов. По умолчанию первичный ключ создается как кластеризованный индекс, но вместо него можно выбрать некластеризованный, предпочтительно после создания кластеризованного индекса. Таким образом, вы можете иметь сгенерированный целочисленный столбец в качестве кластерного индекса и, скажем, имя файла nvarchar (128 символов) в качестве первичного ключа. Это может быть лучше, потому что ключ кластеризованного индекса узок, даже если вы сохраняете имя файла как термин внешнего ключа в других таблицах - хотя этот пример является хорошим примером для того, чтобы не делать этого.
Если ваш дизайн включает в себя импорт таблиц данных, которые содержат неудобный первичный ключ для идентификации связанных данных, то вы в значительной степени застряли с этим.
https://www.techopedia.com/definition/5547/primary-key описывает пример выбора, сохранять ли данные с номером социального страхования клиента в качестве ключа клиента во всех таблицах данных, или генерировать произвольный customer_id, когда вы зарегистрировать их. На самом деле, это серьезное злоупотребление SSN, независимо от того, работает он или нет; это личная и конфиденциальная ценность данных.
Таким образом, преимущество использования фактического факта в качестве ключа заключается в том, что, не возвращаясь к таблице «Клиент», вы можете получать информацию о них в других таблицах - но это также проблема безопасности данных.
Кроме того, у вас возникли проблемы, если SSN или другой ключ данных были записаны неправильно, поэтому у вас неверное значение в 20 ограниченных таблицах, а не только в «Заказчике». В то время как синтетический customer_id не имеет внешнего значения, поэтому он не может быть неправильным значением.
источник