Объяснение NHibernate HiLo - PullRequest
       9

Объяснение NHibernate HiLo

34 голосов
/ 29 апреля 2010

Я изо всех сил пытаюсь понять, как работает генератор HiLo в NHibernate. Я прочитал объяснение здесь , которое немного прояснило ситуацию.

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

В объяснении по вышеприведенной ссылке также говорится:

Например, предположим, что у вас есть последовательность «high» с текущим значением 35, а число «low» находится в диапазоне 0-1023. Затем клиент может увеличить последовательность до 36 (чтобы другие клиенты могли генерировать ключи при использовании 35) и знать, что ключи 35/0, 35/1, 35/2, 35/3 ... 35/1023 все доступно.

Как это работает в веб-приложении, если у меня нет только одного SessionFactory и, следовательно, одного значения hi. Означает ли это, что в отключенном приложении вы можете получить дубликаты (низкие) идентификаторы в вашей таблице сущностей?

В своих тестах я использовал следующие настройки:

<id name="Id" unsaved-value="0">
  <generator class="hilo"/>
</id>

Я провел тест, чтобы сохранить 100 объектов. Идентификаторы в моей таблице были от 32768 до 32868. Следующее значение hi было увеличено до 2. Затем я снова запустил свой тест, и идентификаторы были в диапазоне 65536 - 65636.

Во-первых, зачем начинать с 32768, а не с 1, а во-вторых, с чего переходить с 32868 на 65536?

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

Наконец, кто-нибудь может дать мне объяснение того, как работает параметр max_lo? Это максимальное количество низких значений (идентификаторов сущностей в моей голове), которые можно создать на основе высокого значения?

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

Спасибо Бен

Ответы [ 4 ]

21 голосов
/ 10 мая 2010

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

Мое лучшее предположение заключается в том, что значение max_lo по умолчанию в NHibernate равно 32768. Таким образом, значение Hi, равное 1, приведет к тому, что ваши идентификаторы начнутся с 32768, и вы достигнете уровня 65535. Значение Hi, равное 2, начнется с 65536 и запустит другие идентификаторы max_lo. .

В основном вы используете значение max_lo для управления фрагментацией Id. 32768, вероятно, не оптимальное значение для каждой ситуации.

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

9 голосов
/ 17 августа 2011

Глядя на ключи, сгенерированные моими объектами Nhibernate 3 HiLo, алгоритм выглядит следующим образом: (Привет * Ло) + Привет

Итак, с моим Hivalue в БД как 390 и с моей конфигурацией следующим образом:

<id name="TimeclockId" column="TimeclockId" type="Int64" unsaved-value="0">
      <generator class="hilo">
        <param name="where">TableId = 1</param>
        <param name="table">HiValue</param>
        <param name="column">NextValue</param>
        <param name="max_lo">10</param>
      </generator>
    </id>

Я перезапускаю пул приложений и получаю (390 * 10) + 390 = 4290, диапазон составляет 4290 - 4300.

Это причина, по которой вы получаете на первый взгляд странные пробелы в ваших первичных ключах, поскольку следующий сгенерированный ключ со значением hi 391 равен 4301, а диапазон 4301 - 4311.

2 голосов
/ 07 октября 2016

Для тех, кто интересуется, как выбрать хорошее значение max_lo, компромисс по существу находится между:

  • Частота, с которой вам нужно запросить новое значение hi из базы данных.
  • Максимальное количество уникальных чисел, которые вы на самом деле можете сгенерировать.

Меньшее значение max_lo обеспечит отсутствие «потери» идентификаторов, что, в свою очередь, определяет момент, когда вы достигнете неявного предела вашего типа данных (который, вероятно, будет int). Цена, которую вы платите, заключается в том, что каждый клиент должен чаще запрашивать и увеличивать значение hi.

Более высокий max_lo полезен для уменьшения частоты запросов, которые получают и увеличивают hi, но приводят к большему количеству потерь.

Метрики, которые необходимо учитывать для определения оптимального значения:

  • Частота, с которой создаются новые сущности, которым требуется идентификатор
  • Частота, с которой приложение перезапускается / перерабатывается (все, что приводит к созданию новой NHibernate SessionFactory)

Давайте рассмотрим веб-приложение, которое размещено в IIS и перерабатывается каждые 24 часа. Объектами являются Customer и Order.

Теперь давайте предположим:

  • 10000 новых заказов за 24 часа
  • 10 новых клиентов за 24 часа

Тогда идеальный max_lo будет 10000 для заказов и 10 для клиентов. Конечно, в реальном мире вы никогда не сможете определить это так точно и четко, но вы должны понять это здесь!

Теперь давайте рассмотрим другой сценарий, где мы выбираем совершенно неправильно (смешно) max_lo:

  • Предположим, что 10 клиентов делают заказы одновременно каждую секунду, при max_lo из 10 заказов каждую секунду происходит избыточный вызов базы данных для увеличения hi.
  • Предположим, что ваше приложение является настольным приложением и установлено на 50 клиентах (вспомогательный персонал?), Каждый из которых запускает его примерно два раза в день. Вместе они создают около 100 билетов службы поддержки в день. Теперь предположим, что мы придерживаемся max_lo по умолчанию 32767. Hi увеличивается 100 раз в день (50 клиентов * 2), что означает, что вы достигнете максимального значения int через менее чем за 2 года , если вы забыли важный факт, что hi увеличивается так часто. Хороший max_lo здесь будет (100 билетов / 50 клиентов) = только 2.

Надеется, что это поможет с концептуализацией алгоритма HiLo и его последствий в целом, а также даст вам математику для фактического прикрепления числа к max_lo.

1 голос
/ 27 февраля 2013

NHibernate 3.1.1 делает это для генерации идентификатора с использованием HiLo

if (lo > maxLo)
{
    long hival = <GetNextHiFromDB>
    lo = hival == 0 ? 1 : 0;
    hi = hival * (this.maxLo + 1L);
}
long result = hi + lo;
lo++;
return result;

Внутри конфигурации NHibernate вы указываете maxLo. Если для maxLo установлено значение 100, вы получите 101 идентификатор для каждого значения hi.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...