Что такое алгоритм Hi/Lo?

Что такое алгоритм Hi/Lo?

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

Я знаю, что Nhibernate обрабатывает его, и мне не нужно знать внутри, но мне просто интересно.

Ответ 1

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

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

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

Ответ 2

В дополнение к Джону:

Используется для отключения работы. Затем клиент может запросить у сервера номер hi и создать объекты, увеличивающие сам номер. Не нужно связываться с сервером до тех пор, пока не будет исчерпан диапазон.

Ответ 3

Алгоритмы hi/lo разбивают область последовательностей на группы "hi". Значение "Привет" назначается синхронно. Каждой группе "hi" дается максимальное количество записей "lo", которые могут быть назначены в автономном режиме, не беспокоясь о параллельных повторяющихся записях.

  1. Токен "hi" назначается базой данных, и два одновременных вызова гарантированно видят уникальные последовательные значения
  2. После получения токена "hi" нам нужен только "incrementSize" (количество записей "lo")
  3. Диапазон идентификаторов задается следующей формулой:

    [(hi -1) * incrementSize) + 1, (hi * incrementSize) + 1)
    

    и значение "lo" будет в диапазоне:

    [0, incrementSize)
    

    применяется от начального значения:

    [(hi -1) * incrementSize) + 1)
    
  4. Когда используются все значения "lo", выбирается новое значение "hi" и цикл продолжается

Вы можете найти более подробное объяснение в этой статье:

И за этой визуальной презентацией также легко следить:

enter image description here

Хотя hi/lo оптимизатор хорош для оптимизации генерации идентификаторов, он не очень хорошо работает с другими системами, вставляющими строки в нашу базу данных, ничего не зная о нашей стратегии идентификаторов.

Hibernate предлагает оптимизатор pooled-lo, который сочетает в себе стратегию генератора hi/lo с механизмом распределения последовательностей взаимодействия. Этот оптимизатор эффективен и совместим с другими системами, являясь лучшим кандидатом, чем предыдущая стратегия идентификаторов hi/lo.

Ответ 4

Lo - это кэшированный распределитель, который разбивает пространство ключей на большие куски, обычно основанные на некотором размере машинного слова, а не на диапазонах значимых размеров (например, получение 200 ключей за раз), которые может разумно выбрать человек.

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

Лучше, чем распределитель Hi-Lo, является распределителем "Линейный блок". При этом используется аналогичный принцип, основанный на таблицах, но выделяются небольшие порции удобного размера и генерируются приятные для человека значения.

create table KEY_ALLOC (
    SEQ varchar(32) not null,
    NEXT bigint not null,
    primary key (SEQ)
);

Чтобы выделить следующие, скажем, 200 ключей (которые затем хранятся в качестве диапазона на сервере и используются по мере необходимости):

select NEXT from KEY_ALLOC where SEQ=?;
update KEY_ALLOC set NEXT=(old value+200) where SEQ=? and NEXT=(old value);

При условии, что вы можете зафиксировать эту транзакцию (используйте повторные попытки для обработки конфликта), вы выделили 200 ключей и можете распределять их по мере необходимости.

При размере порции всего 20 эта схема в 10 раз быстрее, чем выделение из последовательности Oracle, и на 100% переносима среди всех баз данных. Выделение производительности эквивалентно привет-ло.

В отличие от идеи Амблера, она рассматривает пространство клавиш как непрерывную линейную числовую линию.

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

Идея г-на Амблера, для сравнения, выделяет старшие 16- или 32-битные и генерирует большие неприветливые для человека ключевые значения в качестве приращения высоких слов.

Сравнение выделенных ключей:

Linear_Chunk       Hi_Lo
100                65536
101                65537
102                65538
.. server restart
120                131072
121                131073
122                131073
.. server restart
140                196608

Что касается дизайна, его решение существенно сложнее по числовой линии (составные ключи, большие продукты hi_word), чем Linear_Chunk, но при этом не дает сравнительного преимущества.

Дизайн Hi-Lo возник на ранних этапах OO-картографирования и постоянства. В наши дни каркас персистентности, такой как Hibernate, предлагает более простые и лучшие средства выделения по умолчанию.

Ответ 5

Я обнаружил, что алгоритм Hi/Lo идеально подходит для нескольких баз данных с сценариями репликации, основанными на моем опыте. Представьте себе это. у вас есть сервер в Нью-Йорке (псевдоним 01) и еще один сервер в Лос-Анджелесе (псевдоним 02), тогда у вас есть таблица PERSON... поэтому в Нью-Йорке, когда человек создает... вы всегда используете 01 в качестве значения HI, а значение LO - следующее. Пример.

  • 010000010 Джейсон
  • 010000011 David
  • 010000012 Theo

в Лос-Анджелесе вы всегда используете HI 02. например:

  • 020000045 Rupert
  • 020000046 Освальд
  • 020000047 Mario

Итак, когда вы используете репликацию базы данных (независимо от того, какой бренд), все первичные ключи и данные объединяются легко и естественно, не беспокоясь о дублирующих первичных ключах, коллингах и т.д.

Это лучший способ пойти в этом сценарии.