Гид Дилемма основного/внешнего ключа SQL Server

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

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

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

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

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

Ответ 1

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

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

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

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

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

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

Да, я знаю - там newsequentialid() в SQL Server 2005 и выше - но даже это не является поистине и полностью последовательным и, следовательно, также страдает от тех же проблем, что и 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 в используемой таблице как ключ кластеризации. В противном случае ваша производительность обязательно будет танка и сильно пострадала.

Ответ 2

Недостаток использования 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/

Ответ 3

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

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

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

Ответ 4

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

Почему вы все равно должны меняться от целых?

Ответ 5

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

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