Не могу объяснить производительность Nhibernate с помощью Guid и Native Keys.

Недавно у нас был традиционный и постоянный (согласно поиску SO) аргумент о назначенных первичных ключах GUID и автоинкременте. Мы используем MSSQL 2008R2, NHibernate 2.05 и .NET 4.0.

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

Я написал простое приложение, которое просто вставляет 2 миллиона объектов по одной строке за сеанс в базу данных, и единственная разница между двумя запусками приложения — это тип ключа. Оба ключа сгруппированы - так что, насколько я читал, это хороший случай для автоматического увеличения и худший случай для Guid.

Посмотрев на результаты, я был немного шокирован....

Не желая, чтобы на меня обрушился террор Зеда Шоу за невыполнение надлежащих статистического анализа, я загрузил данные в R и построил график (см. ниже) и получил следующую сводную статистику:

Ключи GUID:

Мин: 0,00

1-й квартиль: 0,00

Медиана: 0,00

Среднее значение: 1,975

Стандартное отклонение: 13,577490

3-й квартиль: 1,0

Макс: 3824,0

Собственные (автоинкрементные целочисленные) ключи

Мин: 0,00

1-й квартиль: 0,00

Медиана: 0,00

Среднее: 1,644

Стандартное отклонение: 12,491320

3-й квартиль: 0,00

Макс: 1932,00

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

GUID : 0,002594

Нативный: 0,002594

Значения r-квадрата вызывают у меня наибольшую озабоченность, поскольку из моего (правда, ограниченного) понимания статистики нет никакой корреляции между размером таблицы и скоростью вставки в любом случае.

Меня беспокоит то, что результаты, которые я получаю, не соответствуют общепринятым представлениям, и мне интересно, может ли кто-нибудь в стране SO помочь мне объяснить результаты. Я вижу несколько возможностей:

  1. Проблема производительности с GUID была проблемой с предыдущими версиями сервера MSSQL, однако больше не является проблемой.
  2. Я написал плохой эксперимент, и результаты, которые я получаю, бесполезны.
  3. Разница в 0,331 мс между ними на самом деле значительна, если смотреть на производительность базы данных, и я не рассматриваю это значение разумно.
  4. Обратный путь к базе данных для получения идентификатора при использовании ключа идентификатора с автоинкрементом влияет на производительность.
  5. Использование четырехъядерного компьютера для локального тестирования означает, что имеется достаточно свободного ЦП для работы с индексацией в фоновом потоке.
  6. Вся статистика, которую я видел, относится к необработанному SQL с использованием сгенерированных GUID, и тот сценарий, который я тестирую (с использованием NHibernate), представляет собой другой случай.

Заранее извиняюсь, я не большой гуру баз данных, поэтому мне сложно объяснить эти результаты.

Ваше здоровье,

Айдос

сюжет


person Aidos    schedule 19.01.2012    source источник
comment
Я думаю, что могу попробовать сохранить некоторые графы объектов, а также проверить производительность каскада — это может помочь выделить некоторую разницу в производительности между двумя типами ключей.   -  person Aidos    schedule 19.01.2012
comment
Чему именно вы ищете объяснение?   -  person Phil Degenhardt    schedule 20.01.2012
comment
Почему я не вижу прогнозируемого замедления вставки, о котором говорится во многих блогах/ссылках SO.   -  person Aidos    schedule 20.01.2012


Ответы (1)


Ответ № 2, вы написали эксперимент, который неправильно отражает условия «принятой мудрости». Три проблемы:

Сначала вы вставляете «одну строку за сеанс». Это не тот случай, к которому относится «принятая мудрость». Возьмем пример документации «Кошки, котята и помощник», где у кошки есть один помощник и много котят. Обсуждается обновление и вставка целых семейств кошек за раз, а не по одному ряду за раз. Накладные расходы на транзакцию для каждой строки привнесут много шума в ваш тест.

Во-вторых, «предположение, что должна быть линейная зависимость между размером таблицы и временем, необходимым для вставки строки», также неверно. Структура BTree, используемая для хранения таблиц, в общем случае имеет время вставки около O(log n).

В-третьих, причина, по которой вы видите «более медленные» вставки в guids по сравнению с идентификаторами, связана с деталями BTree. Вставки в середину дерева выполняются медленнее, потому что потенциально перемещается гораздо больше данных, а разделение страниц гораздо менее вероятно. Алгоритм guid-comb и генератор были созданы, чтобы смягчить эту проблему. Guid-comb гарантирует, что идентификаторы, созданные в будущем, всегда будут больше, чем идентификаторы, созданные в прошлом, что приводит к вставке в конец таблицы, что намного эффективнее. Аналогичная стратегия используется функцией newsequentialid в сервере sql.

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

person JeffreyABecker    schedule 19.01.2012
comment
Спасибо за ваш ответ! Приложение, которое я имею в виду, не должно поддерживать сценарий семейства кошек - это будут только пакетные вставки, где проявляется проблема? - person Aidos; 20.01.2012
comment
Я думаю, что мой вопрос лучше сформулировать так: в типичном сценарии веб-приложения система будет вставлять только 1 или 2 строки на транзакцию, учитывая ваш ответ выше, означает ли это, что эта проблема не возникнет (поскольку будет без объемных вставок)? - person Aidos; 20.01.2012
comment
Я бы поостерегся обобщать веб-приложения на одну строку на цикл. Я сталкивался со множеством веб-приложений, в которых 5-10 строк за круговой обход не являются чем-то необычным. Но если ваше единственное условие — одна строка за раз, то да, вы не увидите проблем с идентичностями. - person JeffreyABecker; 24.01.2012