2009-05-27 3 views
4

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

Я предполагаю, что существующие данные останутся довольно фрагментированными, но новые данные будут менее фрагментированными. Это означало бы, что я должен подождать некоторое время, прежде чем изменять индекс PK от некластеризованного до кластеризованного.

Мой вопрос: есть ли у кого-нибудь опыт? Есть ли что-то, что я забыл, что я должен быть осторожен?

ответ

3

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

Как вы сказали, вы сделали какие-либо измерения, чтобы показать, что фрагментация на самом деле влияет на вашу систему? Просто глядя на индекс и видя, что «фрагментирован 75%», не подразумевает, что на время доступа влияет. Есть много других факторов, которые вступают в игру (ожидаемая продолжительность жизни в буферном пуле, скорость чтения и записи, локальность последовательных операций, параллелизм операций и т. Д. И т. Д.). Хотя переключение с гидов на последовательные концы обычно безопасно, вы можете ввести проблемы еще. Например, вы можете видеть конкуренцию завязки страниц для интенсивной OLTP-системы с вставкой, поскольку она создает страницу с горячей точкой, где накапливаются вставки.

+0

Thanks Remus - интересный комментарий. Я слышал о «конфликте закладок страницы» один раз, но, похоже, это редко упоминается в аргументах для и против GUID. Вы правы, я, вероятно, ошибался в своих мыслях о ожидании, прежде чем переключиться на кластеризованный индекс. – cbp

+0

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

-4

Если это SQL Server, вы генерируете Guid, вызывая newid(). Это не подходит для первичных ключей. Используйте целочисленный столбец идентификатора для первичного ключа и сделайте свой Guid суррогатным ключом (и столбцом строки guid).

+0

Именно поэтому он спрашивает о переключении на newsequentialid(). –

4

Вы можете подумать об использовании comb guids, в отличие от newsequentialid.

cast(
    cast(NewID() as binary(10)) + 
    cast(GetDate() as binary(6)) 
as uniqueidentifier) 

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

+0

Я думал о них, хотя, я думаю, я бы предпочел пойти с «поддерживаемой» функцией. Я полагаю, что теоретически я мог бы перевести таблицу из newid() в COMB без проблем, хотя, поскольку типы данных одинаковы. – cbp

0

Спасибо, yfeldblum! Ваше простое и краткое объяснение GUID COMB действительно помогло мне. Я действительно смотрел на то, чтобы сделать обратное этому сообщению: мне пришлось уйти от того, чтобы полагаться на newsequentialid(), так как я пытался перенести db SQL Server 2012 на Azure, а функция newsequentialid() там не поддерживается.

Я был в состоянии изменить все мои таблицы PK по умолчанию прочесывать GUIDs, со следующим синтаксисом:

ALTER TABLE [dbo].[Company] 
ADD CONSTRAINT [DF__Company__Company_ID__72E6D332] 
    DEFAULT (CONVERT([uniqueidentifier],CONVERT([binary](10),newid(),0)+CONVERT([binary](6),getdate(),0),0)) FOR [CompanyId] 
GO 

Мой SQL2012 дб теперь счастливо живет в облаке Azure.