Как лучше всего использовать первичные ключи в таблицах?


256

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

  1. Целочисленный столбец идентификаторов, который автоматически увеличивается.
  2. Уникальный идентификатор (GUID)
  3. Столбец с коротким символом (x) или целым числом (или другим относительно небольшим числовым типом), который может служить столбцом идентификатора строки

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

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

Вопрос :-)

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

  • Дата и время / характер
  • Дата и время / число
  • Дата и время / VARCHAR
  • символ / NVARCHAR / NVARCHAR

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

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

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

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


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

Ответы:


254

Я следую нескольким правилам:

  1. Первичные ключи должны быть настолько маленькими, насколько это необходимо. Предпочитайте числовой тип, потому что числовые типы хранятся в гораздо более компактном формате, чем символьные форматы. Это связано с тем, что большинство первичных ключей являются внешними ключами в другой таблице, а также используются в нескольких индексах. Чем меньше ваш ключ, тем меньше индекс, тем меньше страниц в кеше вы будете использовать.
  2. Первичные ключи никогда не должны меняться. Обновление первичного ключа всегда должно быть исключено. Это потому, что он, скорее всего, будет использоваться в нескольких индексах и использоваться в качестве внешнего ключа. Обновление одного первичного ключа может вызвать эффект изменений.
  3. НЕ используйте «первичный ключ вашей проблемы» в качестве первичного ключа вашей логической модели. Например, номер паспорта, номер социального страхования или номер контракта сотрудника, поскольку эти «первичные ключи» могут меняться в реальных ситуациях.

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


3
Мне это нравится! Есть ли у вас какая-либо документация для обоснования ваших "правил"? Спасибо!
Ллойд Коттен

4
Нет, просто опыт. При работе с «маленькими» базами данных это не так важно. Но когда вы имеете дело с большими БД, все мелочи имеют значение. Только представьте, если у вас есть 1 миллиард строк с int или long pk, по сравнению с использованием текста или guid. Там огромная разница!
Logicalmind

44
Просто не забудьте поместить этот уникальный индекс в естественный ключ (если он действительно существует, что часто не так), когда вы используете искусственный ключ.
HLGEM

3
@Lloyd Cotten: Вот что говорит поставщик больших систем обработки данных в поддержку правила № 1: skyfoundry.com/forum/topic/24 . Это убедило меня вернуться к Ints
hobs

4
даже если вы «знаете», что «естественный ключ мал и никогда не изменится», подумайте дважды. «Мы никогда не будем повторно использовать эти коды» - известные последние слова .... О единственных вещах, которые попадают в категории малых, никогда не меняющихся, являются iso и другие стандарты (коды стран, коды аэропортов iata,). Такие вещи, как «что представляет собой двухбуквенное представление для этого внутреннего бренда» ... подумайте дважды, прежде чем предположить, что «это» никогда не изменится, и вы находитесь на расстоянии одного финансового решения от перестройки базы данных.
Эндрю Хилл

90

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

  • Штаты США: я бы выбрал код штата («Техас» и т. Д.), А не штат = 1 для Техаса
  • Сотрудники: я обычно создавал бы искусственный employee_id, потому что трудно найти что-то еще, что работает. SSN или его эквивалент может работать, но могут быть проблемы, например, у нового участника, который еще не предоставил свой SSN.
  • История зарплаты сотрудника: (employee_id, start_date). Я бы не стал создавать искусственный employee_salary_history_id. Какой пункт это послужило бы (кроме «глупой последовательности» )

Везде, где используются искусственные ключи, вы всегда должны объявлять уникальные ограничения на естественные ключи. Например, используйте state_id, если необходимо, но тогда вам лучше объявить уникальное ограничение на код_состояния, в противном случае вы обязательно в конечном итоге получите:

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas

9
В некоторых случаях с SQL Server 2005/2008 естественный (текстовый) ключ может быть быстрее, чем ключ int. У меня есть приложение с дружественным кодом из 7-8 символов, которое мы используем в качестве первичного ключа, и оно было быстрее (и часто более удобным), чем суррогатное int. В любом случае нам был нужен код, чтобы у нас был читабельный / запоминающийся код, который мы могли бы безопасно передавать без конфликтов в другой экземпляр приложения (несколько сайтов, которые объединяются в более крупный сайт).
Lambacck

1
+1 Хороший ответ. Тем не менее, я бы назначил сотрудника по персоналу доверенным источником идентификатора сотрудника, то есть сотрудника, ответственного за проверку сотрудников в реальной жизни, которые могут использовать такие идентификаторы, как SSN, использовать ссылки и т. Д. Отдел персонала должен быть доверенным источник идентификаторов сотрудников, а не СУБД!
onedaywhen

@ onedaywhen- Я бы не стал. доверяй персоналу. Люди уходят, приходят новые и имеют разные идеи. Предоставьте им доступ к идентификатору, который они считают уникальным / который они хотят использовать, но внутренне для db dba должна принять собственное решение
Дейв Пайл

1
Обратите внимание, что SSN не обязательно уникален в каждой стране. По крайней мере , в Австрии, несколько человек , возможно , одни и те же номера
Maja

Также в некоторых странах (я думаю, даже в США) они фактически рекомендуют не делиться SSN.
Стейн де Витт

25

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

Допустим, у нас есть эти таблицы и столбцы:

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

Если последний бит не имеет смысла, он Invoice.CompanyIdявляется частью двух внешних ключей, одного для таблицы CostCentre и одного для таблицы CostElement . Первичный ключ ( InvoiceId , CompanyId ).

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

Чем меньше шансов облажаться, тем лучше.


6
Это недооцененный недостаток при использовании суррогатных ключей. Если в таблице есть суррогатный ключ, я все равно могу использовать его для такого рода ограничений. К сожалению, хотя для ограничения требуется индекс, и было бы странно создавать уникальный индекс для (surrogate_key, other_column), когда (surrogate_key) сам по себе уникален. Кроме того, (other_column) часто полностью избыточен в таблице карты, поскольку (surrogate_key) уникален во внешней таблице. Суррогаты действительно могут все испортить.
Самуэль Даниэльсон

24

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

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


1
Я работал с несколькими базами данных, которые использовали SSN или Tax ID в качестве первичных ключей. Неэффективно, когда дело доходит до ссылок на хранилище и внешний ключ Не говоря уже о том, что SSN человека может измениться. Так что я с тобой полностью согласен.
Алекс Йоргенсон

13

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

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

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

Но нет оправдания отсутствию ключа.

RE: РЕДАКТИРОВАТЬ

Да, есть много споров по этому поводу: D

Я не вижу очевидного преимущества в натуральных ключах, кроме того, что они являются естественным выбором. Вы всегда будете думать в Имя, SocialNumber - или что-то в этом роде - вместо idPerson .

Суррогатные ключи являются ответом на некоторые проблемы, которые возникают у естественных ключей (например, распространение изменений).

Когда вы привыкаете к суррогатам, это кажется более чистым и управляемым.

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


13
Люди «думают лучше» с помощью естественных ключей. Машины и базы данных, нет.
FDCastel

11

Таблицы должны иметь первичный ключ все время. Когда это не так, это должны были быть поля AutoIncrement.

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

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


Я согласен. А в случае, когда нужно вставить много данных, удалите ограничение первичного ключа (или используйте INSERT IDENTITY ON в TSQL) и верните его потом :)
Эндрю Роллингс

1
Есть исключения: таблицы ссылок очевидно
annakata

Другая причина: если нет PK / уникального ключа, браузеры таблиц (я имею в виду что-то вроде Access / SQL Server Management Studio) будут отказываться обновлять / удалять одну строку с дублированной строкой. Вам придется написать SQL для этого.
Деннис С

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

9

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

Просто процитирую несколько пунктов:

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

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

Естественные ключи (как правило) нарушают правила. Суррогатные ключи соответствуют правилам. (Вам лучше прочитать эту статью, она стоит вашего времени!)


7

Что особенного в первичном ключе?

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

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

  • ВНЕ: К сожалению, побочный эффект большинства баз данных, разрабатываемых и разрабатываемых прикладными программистами (которым я иногда являюсь), заключается в том, что то, что лучше всего подходит для приложения или среды приложения, часто определяет первичный ключ выбора таблиц. Это приводит к использованию целочисленных ключей и ключей GUID (так как они просты в использовании для каркасов приложений) и дизайнам монолитных таблиц (поскольку они уменьшают количество объектов каркаса приложений, необходимых для представления данных в памяти). Эти решения по проектированию баз данных на основе приложений приводят к значительным проблемам согласованности данных при использовании в масштабе. Прикладные структуры, разработанные таким образом, естественным образом приводят к созданию таблиц за раз. «Частичные записи» создаются в таблицах, а данные заполняются с течением времени. Взаимодействие с несколькими таблицами исключается или когда используется, приводит к несогласованности данных, когда приложение функционирует неправильно. Эти конструкции приводят к получению бессмысленных (или трудных для понимания) данных, распределению данных по таблицам (чтобы понять текущую таблицу, вам нужно взглянуть на другие таблицы) и дублированию данных.

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

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

Сказав это, я благодарен за многие плохо спроектированные базы данных, которые существуют сегодня на предприятиях (бессмысленные-суррогатные ключи-данные-повреждены-1NF), потому что это означает, что существует бесконечный объем работы для людей, которые понимают правильное проектирование баз данных. , Но с грустной стороны, это иногда заставляет меня чувствовать себя как Сизиф, но я держу пари, что у него был один черт 401k (до крушения). Держитесь подальше от блогов и веб-сайтов для важных вопросов дизайна базы данных. Если вы разрабатываете базы данных, посмотрите CJ Date. Вы также можете ссылаться на Celko для SQL Server, но только если сначала будете держать себя за нос. На стороне Oracle, ссылка Том Кайт.


1
«По этой логике вы никогда не должны удалять запись из таблицы с одним ключом, а затем добавлять другую запись со вторым ключом». - Для этого есть причина, и именно это будет делать предложение «ON DELETE RESTRICT» для внешнего ключа. В некоторых случаях (скажем, где требуется контрольный журнал) «удаленное» логическое поле было бы лучше, чем разрешение на удаление записи.
Waz

6

Естественный ключ, если таковой имеется, обычно лучше. Итак, если datetime / char однозначно идентифицирует строку и обе части имеют значение для строки, это здорово.

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


9
Обычно лучше? У меня нет никакой научной основы, но я почти уверен, что большинство людей предпочитают суррогатный ключ, а не натуральный. Во многих случаях нет естественного ключа.
JC.

3
ВСЕГДА должен быть естественный ключ для любой строки в вашей базе данных. Этот «естественный» ключ может быть чем-то, сгенерированным в деловом мире или вашей технической системой, но он всегда должен существовать.
Том Х

2
Если в вашем мире именно это определено как единственный способ идентифицировать строку в таблице, тогда да. Конечно, когда дизайнер выбирает создание GUID для PK, обычно это происходит потому, что он не выполнил работу по поиску РЕАЛЬНОГО естественного ключа, поэтому в этом случае GUID НЕ является естественным ключом.
Том Х

8
2. Если вы возьмете свой ключ из мира природы, мир природы изменится, чтобы сломать ваш ключ. Если вы используете номер телефона, вы получите двух пользователей из одной семьи. Если вы используете фамилию, они женятся. Если вы используете SSN, законы о конфиденциальности изменятся и потребуют их удаления.
Джеймс Орр

2
@ Барри: RE: # 2. если мир природы меняется и это приводит к изменению вашего естественного ключа, это означает, что вы выполнили плохую работу, выбрав естественный ключ. По определению, естественный ключ не меняется со временем.
Том Х

6

Вот мое собственное правило, на котором я остановился после 25 лет опыта разработки.

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

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

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

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


5

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

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

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


8
И я видел данные, где SSN не уникален, хотя это должно быть. Будьте очень осторожны с естественными ключами, если вы импортируете свои данные из другого источника!
HLGEM

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

4

Я подозреваю, что свернутая газетная терапия Стивена А. Лоу требуется для дизайнера исходной структуры данных.

Кроме того, GUID в качестве первичного ключа может привести к снижению производительности. Я бы не рекомендовал это.


2
Сказать, что это повышение производительности - преждевременная оптимизация. В некоторых случаях требуются руководства (отключенные клиенты, объединение таблиц в будущем, репликация)
JC.

2
«Преждевременная оптимизация» - это слишком употребляемая фраза на SO (ИМХО)! Да, GUID могут потребоваться в некоторых случаях, но Эндрю правильно указал, что они не должны использоваться в качестве типа данных по умолчанию, независимо от того, требуются они или нет.
Тони Эндрюс

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

Или используйте оба. Имейте первичный ключ на основе int / long для быстрого быстрого выбора и объединения, а затем поле guid. По крайней мере, это то, что я делаю. Это неправильно? Разве я не должен этим заниматься? :)
Эндрю Роллингс

Я также использую обе колонки. Но не уверен, что это неправильно или нет. Ты нашел это @AndrewRollings?
YÒGÎ

3

Вы должны использовать «составной» или «составной» первичный ключ, который состоит из нескольких полей.

Это вполне приемлемое решение, иди сюда для получения дополнительной информации :)


3

Я тоже всегда использую числовой идентификатор столбца. В оракуле я использую число (18,0) без реальной причины выше числа (12,0) (или что-то большее, чем целое, а не длинное), возможно, я просто не хочу беспокоиться о получении нескольких миллиардов строк в дБ!

Я также включил созданный и измененный столбец (отметка времени) для базового отслеживания, где это кажется полезным.

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


2
Я также должен отметить, что я не помещаю идентификаторы в таблицы ссылок / соединений, а только в таблицы, содержащие данные.
JeeBee

3

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

Если естественные ключи не могут быть найдены, я предпочитаю GUID для INT ++, потому что SQL Server использует деревья, и плохо всегда добавлять ключи к концу в деревьях.

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

Поскольку мне посчастливилось использовать SQL Server, я могу изучить планы выполнения и статистику с помощью профилировщика и анализатора запросов и выяснить, как мои ключи работают очень легко.


Есть ли у вас документация, подтверждающая это утверждение: «если естественные ключи не могут быть найдены, я предпочитаю GUID для INT ++, потому что SQL Server использует деревья, и плохо всегда добавлять ключи к концу в деревьях». Не скептически, просто пытаюсь скомпилировать документацию.
Ллойд Коттен

1
@Lloyd - Рад, что вы интересуетесь чем-то, что я нахожу очень интересным для себя. Хорошая отправная точка в msdn.microsoft.com/en-us/library/ms177443(SQL.90).aspx
Гуге

2

Я всегда использую поле номера или идентификатора.

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


6
Плохой выбор естественного ключа разработчиком не означает, что естественные ключи плохие.
Том Х

1
Инструмент, который трудно использовать, не является ли чем-то против этого инструмента?
Сквики

1

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

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


1

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


1

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

Вам нужно создать COMID GUID. Хорошая статья об этом и статистике производительности - Стоимость GUID как первичных ключей. .

Также некоторый код для создания COMID GUID в SQL находится в Uniqueidentifier vs identity ( архив ) .


5
ИМХО, guid следует использовать только тогда, когда вам нужно синхронизировать данные между базами данных. В котором автоматически генерируемый идентификатор проблематичен. Разница между использованием guid и использованием базового числового типа заключается в том, что guid потребует 16 байтов на строку, а числовое будет намного меньше.
Logicalmind

Если вы перейдете по ссылке, указанной выше, разница в производительности при использовании COMB Guids будет очень незначительной.
Донни В.

0

Мы выполняем много объединений, и составные первичные ключи просто стали причиной снижения производительности. Простое int или long решает многие проблемы, даже если вы вводите второй ключ-кандидат, но гораздо проще и понятнее объединиться в одной области, чем в трех.


1
Эта стратегия разваливается, когда вам теперь нужно пройти 6 таблиц, чтобы объединить две нужные вам таблицы, потому что составные ключи не были распространены. Это также в конечном итоге требует использования циклов / курсоров для нескольких вставок, что может быть ОГРОМНЫМ скачком производительности.
Том Х

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

0

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

  • ID строки (GUID)
  • Создатель (строка; по умолчанию используется имя текущего пользователя ( SUSER_SNAME()в T-SQL))
  • Создано (DateTime)
  • Отметка

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

Между тем, фактический PK является, если возможно, естественным ключом. Мои внутренние правила примерно такие:

  • Люди - используйте суррогатный ключ, например INT. Если это внутренний, GUID пользователя Active Directory является приемлемым выбором
  • Таблицы поиска (например, StatusCodes) - используйте короткий код CHAR; его легче запомнить, чем INT, и во многих случаях бумажные формы и пользователи также будут использовать его для краткости (например, Status = "E" для "Expired", "A" для "Approved", "NADIS" для "No Asbstos Detected" В образце ")
  • Связывание таблиц - комбинация ФК (например EventId, AttendeeId)

Таким образом, в идеале вы получите естественный, понятный для человека и запоминающийся PK, а также ORM-удобный GUID «один идентификатор на таблицу».

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


1
Вы предлагаете создать таблицы GUID и INT SK для таблиц без строгого естественного ключа?

Вы не обязаны этого делать, но выгода заключается в следующем: а) он упрощает репликацию, если вам это нужно, б) при работе с ORM вы можете присвоить уникальный идентификатор своему объекту в коде перед его сохранением (что полезно, если вы приходится много редактировать ваш объект, возможно, сохраняя его в кеше сессии, прежде чем сохранять его). Ключ INT в этом заведении; GUID это просто бонус.
Кит Уильямс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.