Использовать префиксы и автонумера для первичных ключей? - PullRequest
12 голосов
/ 03 февраля 2009

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

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

Пример 1)

  • AssetId - int (32) - первичный ключ
  • Тип - строка

поэтому некоторые примеры данных выглядят так:

==AssetId======Type===
  12345        "Manhole"
  155415       "Pit"

и т.д.

Другой член команды предложил что-то вроде этого:

Пример 2)

  • AssetId - строка - первичный ключ
  • Тип - строка

поэтому некоторые примеры данных выглядят так:

==AssetId======Type===
  "MH12345"    "Manhole"
  "P155415"    "Pit"

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

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

Какой подход вы бы выбрали? И почему? Есть ли какие-либо преимущества в использовании подхода 1 над 2?

РЕДАКТИРОВАТЬ: Да, я буду использовать AUTO_INCREMENT для подхода 1.

Ответы [ 9 ]

25 голосов
/ 03 февраля 2009

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

7 голосов
/ 03 февраля 2009

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

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

4 голосов
/ 03 февраля 2009

Я бы пошел на первое. Создание уникальных идентификаторов должно быть оставлено на SQL-сервере, и вы не можете создавать их автоматически в поточно-ориентированном виде, если они являются строками. Насколько я понимаю, вам придется как-то справиться с этим самостоятельно?

Скорость является еще одним фактором. Работа со значениями int всегда будет быстрее, чем строки. Я бы сказал, что в индексировании есть и другие преимущества, которые гораздо лучше разбираются в SQL, чем я;)

По моему опыту, иметь строковые идентификаторы не удалось.

3 голосов
/ 17 декабря 2009

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

3 голосов
/ 03 февраля 2009

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

  • Подумайте о том, чтобы иметь отдельную таблицу для Type, скажем, со столбцами Id и Desc, затем создайте внешний ключ TypeId в этой таблице. Еще один шаг вперед, чтобы нормализовать вещь. Но это может быть нежелательно. Сделайте это, если вы думаете, что это служит какой-то цели

  • Делать это String действительно имеет смысл, если позже вы, ребята, подумаете о переходе на UUID. Вам не нужно менять тип данных, тогда

[Изменено]

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

2 голосов
/ 03 февраля 2009

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

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

1 голос
/ 03 февраля 2009

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

==AssetId(PK)==Type========DeprecatedId====
  12345        "Manhole"   "MH64247"
  155415       "Pit"       "P6487246"
0 голосов
/ 17 декабря 2009

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

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

0 голосов
/ 03 февраля 2009

Если ваши активы уже имеют уникальные природные идентификаторы (например, сотрудники с их идентификаторами сотрудников), используйте их. Нет смысла создавать еще один уникальный идентификатор.

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

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

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

...