Каковы плюсы и минусы использования многоколоночных первичных ключей? - PullRequest
14 голосов
/ 05 февраля 2010

Я хотел бы увидеть пример:

  • Когда это уместно
  • Когда это не подходит

Есть ли время, когда выбор базы данных будет иметь значение для приведенных выше примеров?

Ответы [ 7 ]

33 голосов
/ 05 февраля 2010

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

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

В некоторых из этих ответов используется терминология SQL Server, но эти концепции обычно применимы ко всем продуктам СУБД:


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

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

  • Отношения. Если ваш ключ имеет длину 3, 4, 5 столбцов, включая типы символов и другие некомпактныеданные, вы теряете огромных объемов пространства и впоследствии снижаете производительность, если вам необходимо создать связи с внешним ключом для этого ключа в 20 других таблицах.

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

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

Причины использовать многоколонные естественные ключи

  • Хранилище. Многие люди, работающие с базами данных, никогда не работают с достаточно большими, чтобы иметь дело с этим фактором,Но когда в таблице содержатся миллиарды или триллионы строк, вы захотите сохранить в этой таблице абсолютный минимальный объем данных, который вы, возможно, сможете.

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

  • Производительность вставки / обновления .Суррогатные ключи не бесплатны.Если у вас есть набор уникальных столбцов и , которые часто запрашиваются, и поэтому вам необходимо создать индекс покрытия для этих столбцов;Индекс оказывается почти таким же большим, как таблица, которая тратит пространство , а требует обновления второго индекса каждый раз, когда вы вносите какие-либо изменения.Если вам когда-либо удастся иметь только один индекс (кластеризованный индекс) для таблицы, вы должны это сделать!


Вот что сразу приходит на ум. Я обновлюсь, если вдруг что-нибудь вспомню.

3 голосов
/ 05 февраля 2010

Я думаю, что почти всегда лучше (по крайней мере, с точки зрения разработчика приложений) сделать первичный ключ автоматически сгенерированным ключом и создать УНИКАЛЬНОЕ ограничение и индекс для нескольких столбцов.

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

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

3 голосов
/ 05 февраля 2010

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

Если вам нужен первичный ключ с двумя столбцами:

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

Если вам нужен первичный ключ с автоинкрементом:

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

Несколько примеров ...

Подходит:

  • OLTP-системы, в большинстве случаев при реализации большинства отношений «многие ко многим».

недопустимом:

  • Для таблиц измерений в системах OLAP - вы хотите, чтобы ваш ключ измерения был как можно меньше, чтобы таблица фактов была как можно меньше (и быстрее).

  • Для случаев, когда вы не уверены, является ли комбинация уникальной. Конечно, это довольно неприятный пример, но таблица "Person" была бы плохим выбором для многоколоночного PK.

0 голосов
/ 05 февраля 2010

Иногда составные натуральные ключи имеют интуитивный смысл. Например. Предположим, у вас есть таблица для компании (PK - ComapnyId) с некоторыми сведениями о компании в столбцах. У вас также есть требование хранить имя генерального директора компании на протяжении всей ее истории. Естественным инвариантом является то, что одна компания может иметь только одного генерального директора одновременно. Затем интуитивно понятно создать таблицу CompanyCeo с составным PK CompanyId (от FK до CompanyId в таблице Company) + FromDate. Другими столбцами в этой таблице могут быть ToDate и CeoName. Таким образом, вы можете гарантировать, что один и только один генеральный директор может начать работу в конкретную дату.

0 голосов
/ 05 февраля 2010

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

0 голосов
/ 05 февраля 2010

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

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

...