Дилемма Guid первичного / внешнего ключа SQL Server - PullRequest
11 голосов
/ 08 июня 2010

Я столкнулся с дилеммой изменения моих первичных ключей с int-идентификаторов на Guid.Я поставлю свою проблему прямо вверх.Это типичное приложение для управления розничной торговлей с функциями POS и бэк-офиса.Имеет около 100 таблиц.База данных синхронизируется с другими базами данных и получает / отправляет новые данные.

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

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

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

Я буду очень признателен за ваши мысли об этом ...

Ответы [ 5 ]

25 голосов
/ 08 июня 2010

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

Так что если вы действительно должны изменить свои первичные ключи на GUID - попробуйте убедиться, что первичный ключ не является ключом кластеризации, и у вас все еще есть поле INT IDENTITY в таблице, которая используется как ключ кластеризации. В противном случае, ваша производительность обязательно улучшится и получит серьезный удар.

3 голосов
/ 08 июня 2010

Недостаток использования guid по сравнению с int:

Строковые значения не так оптимальны, как целочисленные значения для производительности при использовании в соединениях, индексах и условиях.Требуется больше места для хранения, чем для INT.

Сгенерированные идентификаторы GUID должны быть частично последовательными для лучшей производительности (например, newsequentialid () в SQL 2005) и разрешать использование кластеризованных индексов

для более подробной информации:

http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html

http://blog.sqlauthority.com/2010/04/28/sql-server-guid-vs-int-your-opinion/

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

Мое мнение таково: используйте autoincrement int как PK внутри и используйте уникальный столбец Guid для каждой первичной таблицы, которую вы используете для перемещения строк между базами данных.

Присоединяйтесь к этому столбцу при экспорте данных, не экспортируйте int и сопоставляйте его с int при импорте данных.

Особенно в больших объемах, int намного меньше и быстрее.

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

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

Так что ответ "это зависит". Как и все, что связано с производительностью, вы не можете быть в этом уверены, пока не попробуете.

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

Использование GUID или int для PK действительно зависит от сценария. Будет скачок производительности, изменяющийся с INT на GUID. GUID в 4 раза больше, чем INT. Здесь есть хорошая статья о плюсах и минусах использования GUID.

Почему вы все равно должны перейти от целых чисел?

...