По каким причинам * не * нужно использовать GUID для первичного ключа? - PullRequest
23 голосов
/ 16 июня 2010

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

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

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

Основываясь на ответах, позвольте мне уточнить:

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

  1. Целостность данных, основанная на естественных ключах, может быть разработана, но не предполагается.
  2. Функция первичного ключа - это ссылочная целостность, независимо от производительности, последовательности илиданные.

Ответы [ 8 ]

16 голосов
/ 16 июня 2010

Идентификаторы GUID могут показаться естественным выбором для вашего первичного ключа - и, если вам действительно необходимо, вы, вероятно, можете поспорить, чтобы использовать его для ОСНОВНОГО КЛЮЧА таблицы.

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

Вам действительно нужно разделить две проблемы:

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

2) ключ кластеризации (столбец или столбцы, определяющие«кластеризованный индекс» в таблице) - это физическая вещь, связанная с хранилищем, и здесь маленький, стабильный, постоянно увеличивающийся тип данных - ваш лучший выбор - INT или BIGINT в качестве варианта по умолчанию.

По умолчанию первичный ключ в таблице SQL Server также используется в качестве ключа кластеризации, но это не обязательно должно быть так!Я лично наблюдал значительное увеличение производительности, когда разбивал предыдущий первичный / кластерный ключ на основе GUID на два отдельных ключа - первичный (логический) ключ на GUID и ключ кластеризации (упорядочения) на отдельном INT IDENTITY (1,1) столбец.

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

Да, я знаю - в SQL Server 2005 и более поздних версиях newsequentialid() - но даже это не совсем и полностью последовательно и, следовательно, также страдает от того жепроблемы, связанные с GUID - чуть менее заметно.

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

Быстрый расчет - использование INT в сравнении с GUID в качестве первичного ключа и ключа кластеризации:

  • Базовая таблица с 1 000 000 строк (3,8 МБ против 15,26 МБ)
  • 6 некластеризованных индексов (22,89 МБ против 91,55 МБ)

ВСЕГО: 25 МБ против 106 МБ - и это только на одной таблице!

Еще немного пищи для размышлений - отличный материал от Кимберли Триппа - прочитайте его, прочитайте еще раз, переварите!Это действительно Евангелие для индексирования SQL Server.

Марк

14 голосов
/ 16 июня 2010

Джефф Этвуд говорит об этом очень подробно:http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html

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

Guid Минусы:Это колоссальное в 4 раза больше, чем традиционное 4-байтовое значение индекса;это может иметь серьезные последствия для производительности и хранения, если вы не будете осторожныГромоздкий для отладки (где userid = '{BAE7DF4-DDF-3RG-5TY3E3RF456AS10}')Сгенерированные идентификаторы GUID должны быть частично последовательными для лучшей производительности (например, newsequentialid () в SQL 2005) и для возможности использования кластерных индексов.

4 голосов
/ 16 июня 2010

Вы все еще используете естественный ключ каждой таблицы, не так ли?- Очевидно, что одни только ключи GUID не предотвратят дублирование данных, избыточность и, как следствие, потерю целостности данных.

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

4 голосов
/ 16 июня 2010

Добавление к ewwwn:

Плюсы

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

Минусы

  • Толстее.Реальная проблема с тем, что он более толстый, состоит в том, что он потребляет больше места на страницу и больше места в ваших индексах, делая их медленнее.В современном мире дополнительное пространство хранения Guids откровенно неактуально.
  • Вы абсолютно должны быть осторожны с тем, как создаются новые ценности.Действительно случайные значения плохо индексируются.Вы вынуждены использовать направляющую COMB или какой-либо другой вариант, который добавляет в нее последовательный элемент.
3 голосов
/ 16 июня 2010

Простой ответ: это не реляционный.

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

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

1 голос
/ 05 сентября 2010

Интересно, почему нет стандартного типа "miniGUID"?Казалось бы, выполнение приличного хэша для GUID должно дать 64-битное число, которое будет иметь тривиальную вероятность дублирования в любом юниверсе, в котором нет миллиарда или более вещей.Поскольку юниверс, в котором используется большинство идентификаторов GUID / miniGUID, никогда не превысит миллион, а то и меньше миллиарда, я бы подумал, что 8-байтовый miniGuid будет очень полезным.конечно, предположить, что его следует использовать в качестве кластерного индекса;это сильно ухудшило бы производительность.Тем не менее, 8-байтовый miniGUID будет тратить только треть пространства полного GUID (по сравнению с 4-байтовым индексом).

1 голос
/ 16 июня 2010

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

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

0 голосов
/ 16 июня 2010

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

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

...