Как вам ваши первичные ключи?

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

  1. Int / BigInt, автоинкремент которых является достаточно хорошими первичными ключами.
  2. Должно быть не менее 3 столбцов, составляющих первичный ключ.
  3. Идентификатор, GUID и удобочитаемые идентификаторы строк следует рассматривать по-разному.

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

EDIT: у кого-нибудь есть простой образец / алгоритм для создания удобочитаемых идентификаторов для строк, которые хорошо масштабируются?

Поскольку это субъективно, это должна быть вики сообщества.

John Sheehan 01.01.2009 00:14

«Должно быть не менее 3 столбцов, составляющих первичный ключ»? Что это значит? Не могли бы вы дать дальнейшее определение? Или это часть №3?

S.Lott 01.01.2009 03:42

@ S.Lott PK(NEWID(),NEWID(),NEWID()) ;-)

user166390 15.12.2010 22:43

@pst: Почему это требование? Почему в ПК должно быть три столбца? Почему один или четыре?

S.Lott 16.12.2010 06:11

Я мог видеть ПК с тремя столбцами, похожий на ... LocalID (автоматическое увеличение int), GlobalID (GUID), ForeignId (внешний ключ, такой как RolesType) и т. д. LocalID + ForiegnId может быть составной комбинацией клавиш. Guid используется для других веб-сайтов / сервисов. Лично я бы этого не делал, я бы просто использовал Guid + ForiegnId.

Jerad 17.07.2013 23:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
90
5
27 785
26
Перейти к ответу Данный вопрос помечен как решенный

Ответы 26

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

Он все еще хочет знать, КАК это зависит; только осознавая это, можно доверять самому себе в выборе ...

Nicholas Leonard 05.01.2009 02:18

Я поклонник автоинкремента в качестве первичного ключа. В глубине души я знаю, что это отговорка, но она позволяет легко сортировать данные по времени их добавления (ORDER BY ID DESC, f'r instance).

3 колонки звучат ужасно жестко для человеческого анализа.

И это компромисс - какая часть реляционных возможностей вам нужна, по сравнению с тем, чтобы ЭТА ТАБЛИЦА СПРАВА была понятна человеку, который ее опрашивает (по сравнению с хранимой процедурой или программным интерфейсом).

автоинкремент для нас, людей. :-(

Как правило, это зависит от обстоятельств.

Лично мне нравятся int с автоинкрементом.

Но я могу вам сказать одну вещь: никогда не доверяйте данным из других источников как своему ключу. Клянусь, каждый раз, когда я это делаю, он возвращается, чтобы укусить меня. Что ж, больше никогда!

Ответ принят как подходящий

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

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

Это действительно правильный ответ, GUID = Global Unique IDentifier. Это то, что вы хотите от ПК, не так ли? Определить глобально часть данных?

ReaperUnreal 01.01.2009 00:46

GUID не требуется, просто измените шаг на 10 или 20 или сколько серверов вам понадобится, возможно, для синхронизации в будущем.

Robert C. Barth 01.01.2009 01:06

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

stephbu 01.01.2009 04:05

По крайней мере, в 90% случаев GUID не нужен и тратит впустую пространство.

Jonathan Leffler 01.01.2009 06:10

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

Charles Bretana 01.01.2009 23:11

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

Cyril Gupta 03.01.2009 07:10

@bramhaghosh да, гиды отстой ... спасибо.

John Boker 06.02.2009 00:53

@stephbu: функция SQL Server newsequentialid () решает проблему фрагментации индекса, хотя 24 байта все еще немного избыточны, если вам абсолютно не нужна глобальная уникальность. См. msdn.microsoft.com/en-us/library/ms189786.aspx.

ErikE 02.02.2010 20:51

ой, я хотел сказать 16 байт

ErikE 02.02.2010 21:04

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

L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o̲̳̳k̲̳̳e̲̳̳ 08.02.2010 01:25

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

Chris Marisic 04.05.2011 21:37

Магазин, в котором я работал, использовал GUID для всего, даже когда были доступны общедоступные идентификаторы, такие как коды страны или языка ISO. И даже когда было бы достаточно логического или CHAR(1), как для sex. Излишне говорить, что работать с этим было кошмаром.

Lumi 23.05.2011 22:11

Использование GUIDS в качестве ПК увеличивает накладные расходы: sqlskills.com/BLOGS/KIMBERLY/post/…

Michael Paulukonis 16.12.2011 01:36

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

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

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

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

Сменили ссылку, вот обновленная закладка: database-programmer.blogspot.com/2008/09/…

Bryan Rehbein 01.01.2009 00:29

Просто унаследовал такой проект. И первое, что они хотели сделать, взорвало схему. Суррогатные ключи FTW. Бизнес-логика в вашей БД FTL.

Jason 16.12.2010 00:08

There should be atleast 3 columns that make up the primary key.

Я этого не понимаю.

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

Int/ BigInt which autoincrement are good enough primary keys.

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

Первичные ключи должны быть уникальными, но не обязательно постоянными. Следовательно, внешние ключи объявлены с помощью «ON UPDATE CASCADE». Но предположение, что первичные ключи постоянны, помогает упростить многие приложения. Это одно из преимуществ суррогатных ключей.

Bill Karwin 01.01.2009 00:40

Guids.period.

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


обновить, чтобы прояснить мое заявление.

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

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

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

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

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

Наше последнее приложение переживает период тяжелых вставок, который длится около месяца. После этого 90 +% запросов выбираются для отчетности. Чтобы увеличить емкость, я могу подключить дополнительные серверы БД в течение этого большого периода вставки; а позже легко объединить их в единую базу данных для отчетности. Попытка сделать это с помощью INT была бы абсолютным кошмаром.

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

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

stephbu 01.01.2009 04:08

"Guids.period": Это так неправильно. При необходимости следует использовать GUID. Как заметил другой комментатор, это может облегчить жизнь программиста, но влияет на общий размер и производительность БД.

Mitch Wheat 01.01.2009 04:33

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

NotMe 02.01.2009 21:18

GUID мощь подходит для логического первичного ключа, но НИКОГДА НИКОГДА не используйте столбец GUID в качестве ключа кластеризации - вы утонете во фрагментации индекса, что приведет к НИЗКОЙ производительности ...

marc_s 07.01.2009 09:40

Я бы точно не стал объявлять "Guids.period". по этой теме - на самом деле, даже в отрасли, которая настолько переполнена «передовыми практиками», такое утверждение по умолчанию ставит вас на шаткую почву (особенно с этим утверждением). Любая такая болезненная вещь, как GUID, требует серьезного обоснования, и, как говорит JL, я думаю, что большинство из нас сочло бы это крайней мерой. Это как если бы вы написали, не прочитав остальную часть обсуждения.

Hardryv 27.02.2010 01:40

Это сложная тема, осознавали вы это или нет. Может подпадать под раздел этого FAQ по StackOverflow.

Какие вопросы я не должен здесь задавать?

Избегайте вопросов, которые являются субъективными, аргументированными или требуют расширенного обсуждения. Это место для вопросов, на которые можно ответить!

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

Я не позволю обсуждению затягиваться. Мне просто было любопытно увидеть общий консенсус.

Perpetualcoder 01.01.2009 00:34

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

Nicholas Leonard 05.01.2009 02:16

Я использую только int или GUID с автоинкрементом. В 99% случаев я использую автоинкремент int. Это как раз то, что меня научили использовать, когда я впервые узнал о базах данных, и никогда не сталкивался с причинами, по которым их не использовать (хотя я знаю причины, по которым GUID было бы лучше).

Мне нравится автоматическое приращение целых чисел, потому что это помогает с удобочитаемостью. Например, я могу сказать: «Взгляните на запись 129383», и кому-то довольно легко найти ее. С GUID это сделать практически невозможно.

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

dtc 03.01.2009 00:53

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

  • Не слишком ли сложное определение первичного ключа? Избегает ли он введения ненужной сложности ради следования «лучшим практикам»?
  • Есть ли лучший возможный первичный ключ, который потребовал бы меньше накладных расходов для обработки базы данных (например, INTEGER против VARCHAR и т. д.)?
  • Я АБСОЛЮТНО уверен, что инвариант уникальности и определенности моего первичного ключа не изменится?

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

Надеюсь, это поможет добавить ясности ...

Есть некоторые исторические случаи, когда SSN не уникальны.

Bill Karwin 01.01.2009 00:51

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

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

Hardryv 27.02.2010 01:44

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

Andrew G. Johnson 27.02.2010 23:34

Почти всегда целые числа.

У них есть и другие веские причины, помимо того, что они меньше / быстрее обрабатываются. Что бы вы предпочли записать - «404040» или «3463b5a2-a02b-4fd4-aa0f-1d3c0450026c»?

Последнее может быть целым числом с добавлением тире и основанием 16. Но да, 404040 обрабатывается быстрее, чем длинный GUID. Опять же, 0 обрабатывается еще быстрее, потому что не требует ни единого бита данных!

strager 01.01.2009 23:26

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

  • Суррогатные ключи полезны, когда никакой другой атрибут или набор атрибутов в таблице не подходит для однозначной идентификации строк.
  • По возможности предпочтительнее использовать естественные ключи, чтобы сделать таблицу более удобочитаемой. Естественные ключи также позволяют внешнему ключу в зависимой таблице содержать реальное значение вместо суррогатного идентификатора. Например. когда вам нужно сохранить state (Калифорния, Техас, Нью-Йорк), вы также можете использовать естественный ключ char(2) вместо int.
  • При необходимости используйте составные первичные ключи. Не добавляйте суррогатный ключ «id» без необходимости, когда существует совершенно хороший составной ключ (это особенно верно в таблицах «многие ко многим»). Обязанность использовать ключ из трех столбцов в каждой таблице - абсолютная чепуха.
  • GUID - это решение, когда вам нужно сохранить уникальность на нескольких сайтах. Они также удобны, если вам нужно, чтобы значения в первичном ключе были уникальными, но не упорядоченными или последовательными.
  • INT против BIGINT: нечасто, что таблица требует представляет собой 64-битный диапазон для первичных ключей, но с увеличением доступности 64-битного оборудования это не должно быть обузой и дает больше уверенности в том, что вы не переполнитесь. INT, конечно, меньше, поэтому, если пространство ограничено, это может дать небольшое преимущество.

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

Robert C. Barth 01.01.2009 01:23

@Robert: прочтите о "КАСКАДЕ ОБНОВЛЕНИЙ". Но я понимаю, о чем вы говорите, и согласен, что в большинстве случаев лучше использовать суррогатный ключ, потому что атрибуты могут изменяться и быть неуникальными.

Bill Karwin 01.01.2009 03:43

Первичные ключи должны быть неизменными. В этом случае каскадные обновления - это всего лишь уродливая уловка из-за плохого дизайнерского решения. Натуральные ключи НИКОГДА не предпочтительны. То же самое с составными ключами, которые распространяются как чума. Это знает любой человек, имеющий опыт разработки баз данных более 3 месяцев.

F.D.Castel 05.01.2009 09:28

@ F.D .: Я не согласен с вашим однозначным утверждением, и я занимаюсь разработкой баз данных SQL с 1992 года. Но, безусловно, верно, что суррогатные ключи лучше всего могут оставаться неизменными.

Bill Karwin 05.01.2009 21:59

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

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

Кроме того, наличие любого ключа служит нескольким часто несовместимым целям.

  1. Для использования в качестве условий соединения с одной или несколькими записями в дочерних таблицах, которые связаны с этой родительской таблицей. (Явное или неявное определение внешнего ключа в этих дочерних таблицах)
  2. (связанный) Обеспечение того, что дочерние записи должны иметь родительскую запись на родительской вкладке; e (Дочерняя таблица FK должна существовать как ключ в родительской таблице)
  3. Для увеличения количества запросов, которым необходимо быстро найти определенную запись / строку в таблице.

  4. Для обеспечения согласованности данных путем предотвращения вставки повторяющихся строк, представляющих один и тот же логический объект, в таблицу. (Это часто называют «естественным» ключом, и он должен состоять из атрибутов таблицы (сущности), которые относительно инвариантны.)

Ясно, что любой не имеющий смысла, ненатуральный ключ (например, GUID или автоматически сгенерированное целое число) совершенно неспособен удовлетворить # 4.

Но часто со многими (большинством) таблиц полностью естественный ключ, который может предоставить # 4, часто будет состоять из нескольких атрибутов и быть чрезмерно широким или настолько широким, что его использование для целей # 1, # 2 или # 3 приведет к неприемлемым последствия для производительности.

Ответ прост. Используйте оба. Используйте простой автоматически генерируемый интегральный ключ для всех соединений и FK в других дочерних таблицах, но убедитесь, что каждая таблица, которая требует согласованности данных (очень немногие таблицы не имеют), имеет альтернативный естественный уникальный ключ, который предотвратит вставку несовместимых строк данных. .. Кроме того, если у вас всегда есть и то, и другое, тогда все возражения против использования естественного ключа (что, если он изменится? Я должен изменить каждое место, где он упоминается как FK), становятся спорными, поскольку вы не используете его для этого. .. Вы используете его только в одной таблице, где это ПК, чтобы избежать противоречивых дублирующих данных ...

Что касается идентификаторов GUID, будьте очень осторожны при их использовании, поскольку использование идентификаторов в индексе может привести к фрагментации индекса. Наиболее распространенные алгоритмы, используемые для их создания, помещают "случайную" часть guid в наиболее значимые битовые позиции ... Это увеличивает требования к регулярной дефрагментации / переиндексированию индекса по мере добавления новых строк.

Функция SQL Server newsequentialid () решает проблему фрагментации индекса для идентификаторов GUID (хотя 24 байта все еще немного избыточны, если вам абсолютно не нужна глобальная уникальность). См. Msdn.microsoft.com/en-us/library/ms189786.aspx.

ErikE 02.02.2010 20:58

ой, я хотел сказать 16 байт.

ErikE 02.02.2010 21:04

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

Теперь для выбора суррогатного ключа я придерживаюсь столбцов идентификаторов (я работаю в основном в MS SQL Server). GUID слишком велики, и Microsoft рекомендует против использовать их в качестве PK. Если у вас несколько серверов, все, что вам нужно сделать, это сделать приращение 10 или 20, или как вы думаете, максимальное количество серверов, которое вам когда-либо понадобится для синхронизации / расширения, и просто добавьте начальное число для каждой таблицы на каждом последующем сервере. , и у вас никогда не будет конфликта данных.

Конечно, из-за приращения я делаю столбец идентификаторов BigInt (иначе известный как длинный [64 бита]).

Подсчитав немного, даже если вы сделаете приращение 100, в вашей таблице все равно останется 92 233 720 368 547 758 (> 92 квадриллионов) строк.

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

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

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

Cat1.subcatA.record1
Cat1.subcatA.record2
Cat1.subcatB.record1
Cat2.subcatA.record1

Конечно, первое, что хотели клиенты, - это способ перемещать элементы в дереве. Весь набор софта умер до того, как это произошло.

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

Я полностью согласен. Умные клавиши = тупой.

Robert C. Barth 01.01.2009 01:39

Это не значит, что естественные клавиши глупы. Но хороший момент.

user166390 15.12.2010 22:47

Колонки с автоматическим приращением. Я могу заставить свой код без проблем работать с SQL Server или Oracle, один из которых использует идентификацию, а другой - последовательности через мой DAL, и я очень счастлив. Я согласен, GUID иногда необходимы, если вы выполняете репликацию или отправляете данные, чтобы получить их позже после обработки.

Немного актуально, но кое-что, что я начал делать недавно, когда у меня есть небольшие классификационные таблицы (в основном те, которые будут представлять ENUM в коде), - это то, что я сделаю первичный ключ char (3) или char (4). Затем я делаю эти первичные ключи репрезентативными для значения поиска.

Например, у меня есть система котировок для наших внутренних агентов по продажам. У нас есть «Категории затрат», в которых каждой строке котировок назначается одна из ... Итак, у меня есть таблица поиска типов под названием «tCostCategories», где первичный ключ - «MTL», «SVC», «TRV», «TAX», ODC. В других столбцах справочной таблицы хранятся дополнительные сведения, такие как обычные английские значения кодов, «Материал», «Услуги», «Путешествие», «Налоги», «Другие прямые затраты» и т. д.

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

1 номер $ 40 MTL
2 Другое 3-й номер2 $ 150 TRV

Намного проще использовать int для представления категорий, а затем связывать 1, 2, 3 во всех строках - у вас есть данные прямо перед вами, и на производительность, похоже, вообще не влияет (не то, что я ' я действительно проверил.)

Что касается реального вопроса ... Мне нравятся уникальные идентификаторы RowGUID. Я не на 100% в этом вопросе, но разве все строки не имеют внутреннего RowGuid ?? Если это так, то использование RowGuid на самом деле займет меньше места, чем int (или что-то еще в этом отношении.) Все, что я знаю, это то, что если M $ достаточно для использования в GreatPlains, то для меня этого достаточно. (Должен ли я пригнуться ??)

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

Да, вы можете, вы просто не заставляете таблицы подтипов иметь свойство identity, вместо этого они получают явные вставки значения таблицы супертипов. См. stackoverflow.com/questions/2112882/…

ErikE 02.02.2010 21:08

RE GUID's

Остерегайтесь, действительно ли это будет действительно ДЕЙСТВИТЕЛЬНО большая база данных В САМОМ ДЕЛЕ, большая нагрузка и быстрый доступ.

На моей последней работе, где у нас были базы данных от 100 до 500 миллионов записей, наши специалисты по базам данных решительно возражали против GUID и в пользу десятичного числа подходящего размера. Они посчитали, что (в Oracle) разница в размере внутренней памяти для строки Guid - против десятичного значения будет иметь очень заметную разницу при поиске. (Большие ключи = более глубокие деревья для пересечения)

Случайный характер идентификаторов GUID также значительно снижает коэффициент заполнения индексных страниц - это резко увеличивает разрыв и дисковый ввод-вывод.

«Уменьшает коэффициент заполнения»? Не уверен, что это может означать. Фактор заполнения - это одноразовая сделка, определяемая как процент свободного места, запрошенного на конечном уровне индекса во время его построения. Значения GUID по их случайному характеру распределения по ширине конечного уровня при вставках в это свободное пространство, предоставленное коэффициентом заполнения.

Ralph Shillington 17.10.2009 05:32

С каких это пор GUID - это строка? GUID должны храниться внутри как 16 байт любой уважаемой СУБД. Было бы недопустимо хранить 32 байта в шестнадцатеричном представлении! (или 36 с тире, или 38 с фигурными скобками)

ErikE 02.02.2010 21:04

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

Например, в таблице названий и кодов штатов (США) либо имя, либо код могут быть первичным ключом - они составляют два разных ключа-кандидата, и один из них (обычно более короткий - код) выбирается в качестве первичный ключ. В теории функциональных зависимостей (и зависимостей соединения - от 1NF до 5NF) решающее значение имеют ключи-кандидаты, а не первичный ключ.

В качестве контрпримера человеческие имена обычно являются плохим выбором в качестве первичного ключа. Есть много людей, которых зовут «Джон Смит» или другими подобными именами; даже с учетом отчества (помните: оно есть не у всех - например, у меня), есть много возможностей для дублирования. Следовательно, люди не используют имена в качестве первичных ключей. Они изобретают искусственные ключи, такие как номер социального страхования (SSN) или номер сотрудника, и используют их для обозначения человека.

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

Поэтому, когда дело доходит до определения первичного ключа данной таблицы, вы должны посмотреть, что эта таблица представляет. Какой набор или наборы значений столбцов в таблице однозначно идентифицируют каждую строку в таблице? Это ключи-кандидаты. Теперь, если каждый ключ-кандидат состоит из 4 или 5 столбцов, вы можете решить, что они слишком неуклюжи, чтобы сделать хороший первичный ключ (в первую очередь из-за краткости). В таких случаях вы можете ввести суррогатный ключ - искусственно созданное число. Очень часто (но не всегда) в качестве суррогатного ключа достаточно простого 32-битного целого числа. Затем вы назначаете этот суррогатный ключ первичным ключом.

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

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

В некоторых отношениях это довольно жесткая точка зрения.

У меня нет особых проблем с использованием GUID, когда они нужны, но они, как правило, большой (как в 16-64 байтах), и используются слишком часто. Очень часто достаточно хорошего 4-байтового значения. Использование идентификатора GUID, в котором 4-байтового значения будет достаточно, тратит впустую дисковое пространство и замедляет даже индексированный доступ к данным, поскольку на каждую страницу индекса приходится меньше значений, поэтому индекс будет глубже, и для доступа к Информация.

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

Dirk Vollmar 15.01.2009 02:43

(продолжение) Например, Германия заменила 4-значную систему почтовых индексов на 5-значную систему еще в 1990-х годах после повторного объединения.

Dirk Vollmar 15.01.2009 02:44

@divo: Я убежденный сторонник искусственных / суррогатных ключей, но даже я не считаю изменение 4-значного почтового индекса на 5-значное хорошим примером. Почтовые индексы обычно не используются как ключи к чему-либо. (Когда в последний раз вам приходилось запрашивать таблицу PostalCode, чтобы узнать что-нибудь об этом коде? Нет, он почти всегда используется как часть адреса без ссылок в каких-либо других таблицах. Я бы сказал, что ваше предложение почти соответствует использованию суррогатные ключи для самих адресов.)

ErikE 02.02.2010 20:55

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

Dirk Vollmar 02.02.2010 22:18

@divo: Я согласен, что номер социального страхования является хорошим примером.

ErikE 03.02.2010 03:40

Ваша первая точка зрения верна. У этого ограничения есть название. Это называется «целостность сущности». EI требует, чтобы каждая сущность имела уникальную идентичность. Первичные ключи часто удовлетворяют этому требованию, за исключением случаев использования автонумерации. С помощью автонумерации вы можете получить две одинаковые строки, за исключением автонумерации. Обычно это нарушает целостность объекта.

Walter Mitty 12.03.2011 14:56

Почтовый индекс был допустимым примером ... Я делал крупные проекты, связанные с доставкой небольших посылок в США, например время в пути, моделирование затрат, аудит уровня обслуживания, и все это основано на почтовом индексе ... почтовый индекс инъекции (где пакет входит в систему) почтовый индекс места назначения (куда он должен идти) и почтовый индекс доставки (где пошел) ... и это лишь некоторые из них. Получите ставку на доставку - поиск через почтовый индекс. Хотите время в пути? Поиск по почтовому индексу. Спросите менеджера по доставке, как он хочет оценивать работу перевозчика? - по 3-значному почтовому индексу. При моделировании данных никогда не делайте предположений о неизвестных вам доменах.

GWR 07.06.2017 22:15

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

  • Последовательность
  • Независимые от данных (уникальные, не уничтожаются при изменении формата)
  • Человек читаемый

... и нет разумной причины не:

  • Неопределенность в присоединениях? - Таблицы сглаживания - лучшая практика, ИМХО
  • Оптимальные столы? - Удаление одного байта на запись - это преждевременная оптимизация, ИМХО
  • Решение по таблице? - Больше не соответствует
  • Проблемы с масштабированием? - А? Почему?
  • Иерархическая структура данных? - Это денормализация, совершенно другой предмет религии. Достаточно сказать, что я фанат в некоторых случаях в теории, но никогда на практике :)

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

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

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

Очень хороший момент - нужно различать концепцию ЛОГИЧЕСКИЙ первичного ключа (может быть допустимо использовать для этого GUID, особенно если задействована репликация) и концепцию ФИЗИЧЕСКИЕ ключа кластеризации, которая должна быть НИКОГДА как GUID, поскольку это приводит к чрезмерной фрагментации индекса

marc_s 07.01.2009 09:39

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

Ralph Shillington 17.10.2009 03:23

@ Ральф, ты прав, не КАЖДУЮ вставку, но достаточно, чтобы повысить производительность в 20 раз. sql-server-performance.com/articles/per/…

Portman 17.10.2009 06:45

Функция SQL Server newsequentialid () решает проблему фрагментации индекса с помощью идентификаторов GUID (хотя 24 байта все еще немного избыточны, если вам абсолютно не нужна глобальная уникальность). См. Msdn.microsoft.com/en-us/library/ms189786.aspx.

ErikE 02.02.2010 21:00

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

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

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

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

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

ErikE 02.02.2010 21:09

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

Walter Mitty 03.02.2010 17:23

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

Walter Mitty 03.02.2010 17:30

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

Walter Mitty 03.02.2010 17:32

Мне нравится мой уникальный.

Другие вопросы по теме