Подтвердить что ты не робот

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

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

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

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

Например, предположим, что у вас есть "высокая" последовательность с текущим значением 35, а "низкий" номер находится в диапазоне 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 в книге действий, и он все еще не понимает, как это работает в деталях.

Спасибо Бен

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

Итак, с моим Hivalue в DB как 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.

Ответ 3

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.

Ответ 4

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

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

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

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

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

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

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

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

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

Тогда идеальный 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.