Подбор лучшего первичного ключа + система нумерации - PullRequest
22 голосов
/ 02 апреля 2009

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

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

alt text

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

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

Пример 2: Использование сгенерированного программой PK

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

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

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

Спасибо.

РЕДАКТИРОВАТЬ: Спасибо всем за отличные ответы, очень помог мне.

Ответы [ 13 ]

62 голосов
/ 05 апреля 2009

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

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

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

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

7 голосов
/ 02 апреля 2009

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

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

7 голосов
/ 02 апреля 2009

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

4 голосов
/ 02 апреля 2009

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

  • Это на 100% невозможно значение никогда не изменится и что

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

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

3 голосов
/ 10 апреля 2009

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

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

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

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

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

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

1 голос
/ 05 апреля 2009

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

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

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

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


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

Кроме того, вы можете ходить на все собрания, где все спорят друг с другом.

1 голос
/ 02 апреля 2009

Следуйте политике «Не пользуйтесь».

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

Вам необходимо сгенерировать ключи от нескольких хостов.

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

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

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

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

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

0 голосов
/ 12 апреля 2009

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

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

Первичные ключи должны НИКОГДА не показываться пользователем. Делать его читабельным для пользователя не должно быть проблемой. Первичные ключи ДОЛЖНЫ использоваться для связи с внешними ключами. Это их цель. Значение должно быть машиночитаемым и после его создания никогда не должно изменяться.

0 голосов
/ 12 апреля 2009

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

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

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

0 голосов
/ 10 апреля 2009

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

При этом вы, возможно, захотите рассмотреть вопрос о том, является ли ваша база данных:

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

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

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

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

...