Не могу объяснить производительность Nhibernate, используя Guid и Native Keys - PullRequest
2 голосов
/ 19 января 2012

У нас недавно был традиционный и постоянный (согласно поискам 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), - это совсем другой случай.

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

Приветствия

Айдос

plot

1 Ответ

1 голос
/ 20 января 2012

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

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

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

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

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

...