Первичные ключи - нативные, последовательные или GUID-ключи? - PullRequest
3 голосов
/ 21 июля 2009

Читая это и это , а затем читая это (что по иронии судит о двух других), я задаюсь вопросом, насколько велико обсуждение этой темы является? Я парень по SQL Server, и поэтому я склонен использовать Identity, которая автоматически генерируется в форме int. Однако, когда я знаю, что мне потребуется некоторая форма репликации между сервером и сервером или синхронизация между клиентом и сервером, я склонен использовать GUID в качестве моего ключа.

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

Ответы:

@ Дэвид Арчер: В соответствии с вашим комментарием я обновил свой пост, чтобы не произносить «Natural Key». Вы правы в том, что естественный ключ определен как такой . Спасибо за исправление.

Ответы [ 6 ]

4 голосов
/ 21 июля 2009

Я предпочитаю создавать первичные ключи, генерируемые приложением, обычно используя алгоритм lo / hi, реализованный NHibernate (когда я использую его в проекте). В противном случае последовательные идентификаторы GUID работают так же хорошо. Это не просто мой совет, а скорее несколько людей , которые занимались всей этой разработкой намного дольше, чем я.

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

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

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

Природные ключи - порождение дьявола. :)

3 голосов
/ 21 июля 2009

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

Это показывает количество фрагментации для случайных проводников очень важно (Рекомендуется, чтобы «Фрагментация в процентах "должен быть как можно ближе к нулю насколько это возможно). Количество используемых страниц по случайному наведению на 40% выше, а количество места, используемого на каждой странице меньше, поэтому дисковое пространство требуется увеличится.

2 голосов
/ 21 июля 2009

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

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

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

Кроме того, поскольку ключ кластеризованного индекса используется в качестве значения поиска для поиска строки в таблице, он будет добавлен к каждой записи каждого и каждого некластеризованного индекса в вашей таблице, и здесь вступает в игру размер GUID (16 байт) и INT (4 байт) - вы потенциально тратите много места только на отслеживание значений поиска.

Лучшее обсуждение основных / кластеризованных индексов и GUID, о которых я знаю, - это пара статей Кима Триппа, королевы индексирования в SQL Server, - посмотрите их!

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

Марк

2 голосов
/ 21 июля 2009

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

В области репликации SQL Server для достижения уникальности в строки в реплицируемых таблицах добавляется guid, поэтому вполне возможно создать этот проект позже, если вам потребуется.

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

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

1 голос
/ 21 июля 2009

У меня не было большого опыта с этим, но использование GUID для присоединения заставляет меня съеживаться. 4 байта против 36 кажется неприглядным.

Однако я начал использовать GUID в качестве открытых идентификаторов, а не сами поля идентификаторов. Посмотрите на URL выше, 1156712. Если по какой-то причине SO пришлось объединить с другим подобным приложением (скажем, SU), эти идентификаторы вопросов столкнулись бы с одним или другим, пришлось бы изменить его URL, портя любые жестко закодированные ссылки и, возможно Статистика Google также. Принимая во внимание, что если бы каждый элемент был публично идентифицирован посредством использования GUID, а внутренние объединения использовали поля int или bigint, вы могли бы получить лучшее из обоих миров.

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

1 голос
/ 21 июля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...