Выбор лучшего первичного ключа + система нумерации

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

учитывая дизайн базы данных ниже, что было бы лучшим вариантом.

alt text

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

=================   ==================
Road_Number(PK)     Segment_Number(PK)
=================   ==================
 1                   1

Пример 2: используя программу автоматически PK

=================   ==================
Road_Number(PK)     Segment_Number(PK)
=================   ==================
 "RD00000001WCK"     "00000001.1"

(the 00000001.1 означает первый отрезок дороги. Это увеличение каждый раз, когда вы добавляете новый сегмент, например,00000001.2)

Пример 3: используя немного обоих (добавление нового столбца)

=======================    ==========================
ID(PK) Road_Number(UK)     ID(PK)  Segment_Number(UK)
=======================    ==========================
 1     "RD00000001WCK"       1       "00000001.1"

немного справочной информации, мы будем использовать Road Number и Segment Number в отчетах и других документах, поэтому они должны быть уникальный.

мне всегда нравились сохраняя вещи простыми, поэтому я предпочитаю Пример 1, но я читал, что вы не должны выставлять свои первичные ключи в отчетах/документах. Итак, теперь я больше думаю о примере 3.

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

как вы думаете, что нам делать?

спасибо.

EDIT: спасибо каждый для великих ответов, имеет помочь мне много.

13 ответов


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

естественные ключи ключи, основанные на внешне осмысленных данных (якобы) уникальный. Распространенный пример коды продукта, двухбуквенное государство коды (США), номера социального страхования и так далее. Суррогатная или техническая первичные ключи-это те, которые имеют совершенно никакой смысл вне система. Они придуманы исключительно для выявление сущности и обычно автоинкрементные поля (SQL Server, MySQL, другие) или последовательности (особенно Oracle).

по-моему, вы должны всегда использовать суррогатные ключи. Этот вопрос в эти вопросы:

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


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


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

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


Не вкладывайте смысл в свои поля PK, если только...

  • это 100% полностью невозможно, что значение никогда не изменится и что

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

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


Я думаю, что важно помнить, что каждая таблица в вашей базе данных / дизайне может иметь несколько ключей. Это Ключи. см. запись Википедии для ключей-кандидатов

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

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

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

  • Неизменяемый/Прогноз "Стабильный" - значения первичного ключа не должно меняться. Если они это сделают, вы рискуете представляем обновление anomolies
  • Not Null - большинство платформ СУБД требуют, чтобы атрибут(ы) первичного ключа не были null
  • простой - простые типы данных и значения для физического хранения данных и производительности. Целочисленные значения хорошо работают здесь, и это тип данных для большинства суррогатных/автогенераторных ключей

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


следуйте политике "не использовать".

некоторые проблемы, с которыми вы можете столкнуться:

вам нужно создать ключи от более чем одного хоста.

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

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

Если вы объединяете два, вы делаете типажи, которые могут испортить оптимизатор запросов.

вам нужно переклассифицировать дороги и переопределить их границы (т. е. переместить дороги), что подразумевает изменение первичного ключа и, возможно, потерю ссылок.

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


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

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

если будет только один идентификатор, добавьте его в качестве столбца в основную таблицу. Если существует много систем идентификации (и активов обычно много), вам понадобятся еще две таблицы

    Identifier-type table             Identifier-cross-ref table
      type-id             ------------> type-id              (unique
      type-name                         identifier-string     key)
                                        internal-id


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

плюс, вы можете пойти на все встречи, где все спорят друг с другом.


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


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

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


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

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


Я подозреваю, что вы действительно должны использовать Вариант № 3, как многие здесь уже сказали. Суррогатные PKs (целые числа или GUID) - хорошая практика, даже если есть адекватные бизнес-ключи. Суррогаты уменьшат головные боли обслуживания (как вы сами уже отмечали).

Это, как говорится, то, что вы можете рассмотреть, является ли ваша база данных:

  1. сфокусировано на обслуживании данных и транзакционной обработке (т. е. создании / обновлении / удалении операции)
  2. ориентирована на анализ и отчетность (т. е. запросы)

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

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

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


Я надеюсь, вы согласитесь со мной, что каждый элемент дизайна должен иметь единую цель.

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

Что касается новых столбцов в опции 3, Вы должны проверить, могут ли они быть вычислены (лучше всего было бы сделать расчет в слое модели, чтобы их можно было легко изменить, чем если бы расчет сделано в РСУБД) без слишком большого штрафа за производительность от других элементов. Например, вы можете сохранить номер сегмента и номер дороги в соответствующих таблицах, а затем использовать их для создания "00000001.1". Это позволит изменить нумерацию активов на лету.


во-первых, Вариант 2 является абсолютно худшим вариантом. Как индекс, это string, и это делает его медленным. И он генерируется на основе бизнес-правил , которые могут меняться и вызывать довольно большую головную боль.

лично я всегда использую отдельный столбец первичного ключа; и я всегда использую GUID. Некоторые разработчики предпочитают простой INT над GUID из-за пространства на жестком диске. Однако, если возникает ситуация, когда вам нужно объединить две базы данных, GUID почти никогда не столкнутся (в то время как INTs гарантированно сталкиваются).

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