Фрагментация индекса базы данных: последовательный GUID, сохраненный как String, работает нормально, но не сохранен как GUID
Мы используем GUID в качестве первичного ключа (мы знаем, что это не очень хороший вариант, но не можем изменить сейчас). Так как все знают, наши индексы очень быстро фрагментируются. Еще один хороший вариант для замены GUID на Sequential ID. Для этого изменение кода выглядит так:
Старый код:
ObjectName.Id = Guid.NewGuid();
Новый код:
ObjectName.Id = Sequential.NewGuid();
Здесь Sequential - наш статический класс, который создает Sequential GUID, используя "rpcrt4.dll". Но наши тесты показывают, что это не очень хорошо работает с индексами, и они становятся фрагментированными.
Еще один интересный вывод: если мы сохраним этот последовательный GUID как "String" в базе данных, наши индексы не будут фрагментированы.
Теперь у меня есть следующие сомнения / вопросы:
Почему сервер ведет себя по-разному, когда мы сохраняем ту же строку, что и "String" и "GUID"? Насколько я понимаю до сих пор, внутренне он сохраняет все как String.
Есть ли способ настроить базу данных, чтобы сказать об этом, рассматривать наш GUID как строку и относиться к ним одинаково?
Вот некоторые детали окружающей среды:
- База данных: SQLExpress
- Язык кодирования: C#
- Не может полагаться на сервер для генерации ключа, мы должны установить ключ из самого кода.
Даже если не точные решения, указатели на решение также приветствуются.
2 ответа
Guid не сохраняется как строка. Он хранится в виде 16 байтов данных - символы в guid представляют собой шестнадцатеричное представление байтов, где первая пара является наименее значимым значением.
Когда RPCRT4 генерирует последовательные идентификаторы GUID, кажется, что байт 4 считается наименее значимым. Это может быть причиной того, что ваши индексы становятся фрагментированными.
Несмотря на ваши заявления об обратном, я бы порекомендовал использовать функцию NewSequentialID в SQL Server.
Btw. - Вы генерируете свои последовательные руководства на большом количестве компьютеров? Поскольку SQL-сервер в первую очередь сортирует по части guid, определенной для исходного компьютера (подробности в ответе на этот вопрос - который может иметь некоторую полезную информацию для вас: последовательные идентификаторы GUID). В этом случае вы можете получить некоторые результаты, преобразовав Guid в байтовый массив, поменяйте местами его части, а затем заново создайте Guid.
Другим вариантом этого подхода может быть замена идентификатора машины в guid всегда одинаковым статическим значением и использование разных частей Guid (но не отдельных частей временной метки!) Для различения машин - но это будет работать, только если у вас будет очень небольшое количество машин, где вам нужно генерировать направляющие.