База данных SQL Server с кластеризованными GUID PK - переключить кластерный индекс или переключиться на последовательные (гребенчатые) GUID? - PullRequest
5 голосов
/ 09 апреля 2010

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

  • Мы могли бы изменить алгоритм генерации GUID, например, на тот, который использует NHibernate, как описано в этом посте или
  • мы могли бы, для таблиц, которые используются наиболее интенсивно, перейти на другой кластерный индекс, например столбец IDENTITY и сохраните «случайные» GUID как PK.

Можно ли дать какие-либо общие рекомендации по такому сценарию?

У рассматриваемого приложения более 500 таблиц, самая большая из которых в настоящее время составляет около 1,5 млн. Строк, несколько таблиц - около 500 000 строк, а остальные значительно ниже (большинство из них значительно ниже 10K).

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

Спасибо!

Ответы [ 2 ]

7 голосов
/ 09 апреля 2010

Мое мнение ясно: используйте INT IDENTITY для своего ключа кластеризации. Это, безусловно, лучший, самый оптимальный ключ кластеризации, потому что он:

  • маленький
  • стабильный (никогда не должен меняться)
  • уникальный
  • постоянно увеличивается

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

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

Ознакомьтесь с превосходной серией статей Кимберли Триппа о том, почему GUID плохи в качестве ключей кластеризации в SQL Server, здесь:

Марк

3 голосов
/ 09 апреля 2010

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

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

Наконец, я знаю, что вы сказали, что пока не можете этого делать, но, если вам НЕ НУЖНО использовать направляющие в качестве индекса, вы удалите все эти проблемы.

...