Каковы недостатки использования составного / составного первичного ключа?
Каковы недостатки использования составного / составного первичного ключа?
8 ответов
- Может вызвать больше проблем для нормализации ( 2NF, "Обратите внимание, что когда таблица 1NF не имеет составных ключей-кандидатов (ключей-кандидатов, состоящих из более чем одного атрибута), таблица автоматически становится 2NF")
- Больше ненужного дублирования данных. Если ваш составной ключ состоит из 3 столбцов, вам необходимо создать 3 одинаковых столбца в каждой таблице, где он используется в качестве внешнего ключа.
- Как правило, можно избежать с помощью суррогатных ключей ( ознакомьтесь с их достоинствами и недостатками)
- Я могу представить хороший сценарий для составного ключа - в таблице, представляющей отношение N:N, например "Студенты - классы", и ключ в промежуточной таблице будет (StudentID, ClassID). Но если вам нужно хранить больше информации о каждой паре (например, историю всех оценок ученика в классе), вы, вероятно, введете суррогатный ключ.
Нет ничего плохого в том, чтобы иметь составной ключ как таковой, но в идеале первичный ключ должен быть как можно меньше (с точки зрения количества требуемых байтов). Если первичный ключ длинный, то это приведет к раздутым некластеризованным индексам.
Имейте в виду, что порядок столбцов в первичном ключе важен. Первый столбец должен быть как можно более избирательным, то есть как можно более "уникальным". Поиск по первому столбцу будет выполнять поиск, но при поиске только по второму столбцу будет выполняться сканирование, если только во втором столбце нет некластеризованного индекса.
Я думаю, что это специализация дебатов по синтетическим ключам (будь то использование значимых ключей или произвольный синтетический первичный ключ). Я почти полностью остановился на синтетической ключевой стороне этой дискуссии по ряду причин. Вот некоторые из наиболее подходящих:
Вы должны поддерживать зависимые дочерние таблицы в конце внешнего ключа в актуальном состоянии. Если вы измените значение одного из полей первичного ключа (что может произойти - см. Ниже), вам придется каким-то образом изменить все зависимые таблицы, где их значение PK включает эти поля. Это немного сложно, потому что изменение значений ключей сделает недействительными отношения FK с дочерними таблицами, поэтому вам может (в зависимости от параметров проверки ограничений, доступных на вашей платформе) прибегнуть к таким приемам, как копирование записи в новую и удаление старых записей.
На глубокой схеме ключи могут быть достаточно широкими - я видел 8 столбцов один раз.
Изменения в значениях первичного ключа могут быть проблематичными для выявления в процессах ETL, загружаемых из системы. Примером, который я когда-то видел, было приложение MIS, извлекаемое из системы страхового страхования. В некоторых случаях клиент может повторно использовать запись политики, изменяя идентификатор политики. Это было частью первичного ключа таблицы. Когда это происходит, нагрузка хранилища не знает, что было старым значением, поэтому она не может сопоставить новые данные с ним. Разработчик должен был искать в журналах аудита, чтобы определить измененное значение.
Большинство проблем с несинтетическими первичными ключами вращаются вокруг проблем, когда значения PK записей изменяются. Наиболее полезные приложения несинтетических значений - это когда схема базы данных предназначена для использования, например, приложение MIS, где составители отчетов используют таблицы напрямую. В этом случае короткие значения с фиксированными доменами, такие как коды валют или даты, могут быть разумно размещены непосредственно на столе для удобства.
Возьмите пример таблицы с двумя ключами-кандидатами: один простой (с одним столбцом) и один составной (с несколькими столбцами). Ваш вопрос в этом контексте выглядит следующим образом: "Какой недостаток я могу испытать, если я выберу один ключ как" первичный "и выберу составной ключ?"
Во-первых, подумайте, нужно ли вам вообще продвигать ключ: "само существование PRIMARY KEY
в SQL похоже какая-то историческая случайность. Согласно автору Крису Дейту, самые ранние воплощения SQL не имели каких-либо ключевых ограничений и PRIMARY KEY
только позже был добавлен в стандарты SQL. Разработчики стандарта, очевидно, взяли термин от EFCodd, который изобрел его, хотя первоначальное представление Кодда к тому времени было заброшено! (Первоначально Кодд предлагал, чтобы внешние ключи ссылались только на один ключ - первичный ключ - но эта идея была забыта и проигнорирована, потому что она была широко признана как бессмысленное ограничение)." [Источник: блог Дэвида Портаса: долой первичные ключи?
Во-вторых, какие критерии вы бы использовали, чтобы выбрать, какой ключ в таблице должен быть "первичным"? В SQL выбор ключа PRIMARY KEY
является произвольным и специфичным для продукта. В ACE/Jet (он же MS Access) два основных и часто конкурирующих фактора - хотите ли вы использовать PRIMARY KEY
отдавать предпочтение кластеризации на диске или хотите, чтобы столбцы, содержащие ключ, отображались жирным шрифтом на рисунке "Отношения" в пользовательском интерфейсе MS Access; Я в меньшинстве, думая, что стратегия индекса превосходит красивую картинку:) В SQL Server вы можете указать кластерный индекс независимо от PRIMARY KEY
и, кажется, нет никакого специфического преимущества для продукта. Единственным оставшимся преимуществом является то, что вы можете опустить столбцы PRIMARY KEY
при создании внешнего ключа в SQL DDL, поведение стандарта SQL-92 и, во всяком случае, для меня не так уж важно (возможно, это еще одна вещь, которую они добавили в стандарт, потому что эта функция уже широко распространена в продуктах SQL)?) Таким образом, дело не в поиске недостатков, а в том, чтобы выяснить, какое преимущество дает ваш продукт SQL, если он есть, PRIMARY KEY
, Другими словами, единственный недостаток при выборе неправильного ключа - то, что вы можете упустить данное преимущество.
В-третьих, вы скорее намекаете на использование искусственного / синтетического / суррогатного ключа для реализации в вашей физической модели ключа-кандидата из вашей логической модели, потому что вы обеспокоены тем, что при использовании естественного ключа в внешних ключах и соединениях таблиц будут налагаться штрафы за производительность? Это совершенно другой вопрос, и он во многом зависит от вашей "религиозной" позиции по вопросу о естественных ключах в SQL.
Я бы порекомендовал сгенерированный первичный ключ в тех случаях с уникальным ненулевым ограничением на естественный составной ключ.
Если вы используете естественный ключ в качестве первичного, вам, скорее всего, придется ссылаться на оба значения в ссылках на внешний ключ, чтобы убедиться, что вы идентифицируете правильную запись.
- когда вы видите его на диаграмме менее читабельны
- когда вы используете его в запросе соединения менее читабельны
- когда вы используете его для ключа foregein, вы должны добавить проверочное ограничение для всех атрибутов, которые должны быть нулевыми или не нулевыми (если только один равен null, ключ не проверяется)
- обычно требуется больше памяти при использовании его в качестве внешнего ключа
- какой-то инструмент не управляет составным ключом
Нужно больше конкретики.
Слишком далеко, это может привести к чрезмерному усложнению вставок (каждый ключ ДОЛЖЕН существовать) и документации, а присоединенные чтения могут быть подозрительными, если они не завершены.
Иногда это может указывать на некорректную модель данных (действительно ли составной ключ ДЕЙСТВИТЕЛЬНО описывает данные?)
Я не верю, что производительность снижается... просто очень легко может пойти не так.
Основным недостатком использования составного первичного ключа является то, что вы запутаете чертовски типичные генераторы кода ORM.