1. введение
В этом уроке мы объясним алгоритм Hi/Lo. Он используется в основном в качестве стратегии генерации идентификаторов базы данных .
Начнем с обзора алгоритма. Затем мы покажем практический пример, основанный на фреймворке Hibernate. Наконец, мы обсудим варианты использования алгоритмов, их преимущества и недостатки.
2. Обзор алгоритма Hi/Lo
2.1 Определение
Основной целью алгоритма Hi/Lo является создание диапазона чисел, которые можно безопасно использовать в качестве идентификаторов базы данных . Для этого он использует три числовые переменные, обычно называемые high, low и Размер приращения .
Переменная Размер приращения содержит максимальное количество идентификаторов, которые могут быть сгенерированы в одном пакете. Его следует рассматривать как постоянное значение, определенное в начале алгоритма. Любое изменение среды выполнения может вызвать серьезные проблемы в средах, где несколько клиентов используют одну и ту же конфигурацию Hi/Lo для сохранения записей.
Переменная high обычно назначается из последовательности базы данных. В этом случае мы уверены, что никто не получит одно и то же число дважды.
Переменная low содержит текущий присвоенный номер в диапазоне [0 , размер приращения ).
Учитывая эти точки, алгоритм Hi/Lo генерирует значения в диапазоне [( hi – 1) * incrementSize + 1 , ( привет * incrementSize )).
2.2 Псевдокод
Давайте рассмотрим шаги по созданию нового значения с помощью алгоритма Hi/Lo:
- если low больше или равно incrementSize , назначьте новое значение high и сбросьте low на 0
- сгенерируйте новое значение по формуле: ( high – 1) * incrementSize + |/low приращение
- низкое на 1 возвращает сгенерированное значение
3. Практический Пример
Давайте посмотрим алгоритм Hi/Lo в действии. Для этого мы будем использовать фреймворк Hibernate и его реализацию Hi/Lo.
Во-первых, давайте определим объект базы данных для работы:
@Entity public class RestaurantOrder { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "hilo_sequence_generator") @GenericGenerator( name = "hilo_sequence_generator", strategy = "sequence", parameters = { @Parameter(name = "sequence_name", value = "hilo_seqeunce"), @Parameter(name = "initial_value", value = "1"), @Parameter(name = "increment_size", value = "3"), @Parameter(name = "optimizer", value = "hilo") } ) private Long id; }
Это простой заказ в ресторане с одним полем id . Чтобы правильно определить алгоритм Hi/Lo в Hibernate, в определении поля id мы должны выбрать последовательность стратегию – hilo оптимизатор – и указать параметр increment_size .
Чтобы показать алгоритм Hi/Lo в действии, мы сохраним девять заказов в ресторане в цикле:
public void persist() { Transaction transaction = session.beginTransaction(); for (int i = 0; i < 9; i++) { session.persist(new RestaurantOrder()); session.flush(); } transaction.commit(); }
В соответствии с указанным размером приращения в сущности, у нас должно быть только три вызова базы данных для следующего высокого значения. Предполагая, что последовательность базы данных начинается с 1, первая партия сгенерированных идентификаторов будет находиться в диапазоне [1,3].
Когда алгоритм Hi/Lo возвращает 3 и Hibernate запрашивает значение следующего идентификатора, значение переменной low равно константе incrementSize . В этом случае необходимо выполнить следующий вызов базы данных для нового значения high . Имея 2 в качестве нового высокого значения, алгоритм генерирует значения в диапазоне [4,6].
Наконец, выполняется последний вызов базы данных для следующего высокого значения, и сущности присваиваются значения в диапазоне [7, 9].
Журналы гибернации, записанные во время выполнения метода persist () , подтверждают эти значения:
Hibernate: call next value for hilo_seqeunce org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 1 org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 1, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 2, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 3, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator Hibernate: call next value for hilo_seqeunce org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 2 org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 4, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 5, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 6, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator Hibernate: call next value for hilo_seqeunce org.hibernate.id.enhanced.SequenceStructure - Sequence value obtained: 3 org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 7, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 8, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator org.hibernate.event.internal.AbstractSaveEventListener - Generated identifier: 9, using strategy: org.hibernate.id.enhanced.SequenceStyleGenerator
4. Преимущества и недостатки алгоритма
Основным преимуществом алгоритма Hi/Lo является уменьшенное количество вызовов базы данных для следующих значений последовательности. Увеличение значения Размер приращения уменьшает количество обращений к базе данных. Очевидно, что это означает повышение производительности нашего приложения. В дополнение к этому, алгоритм Hi/Lo является предпочтительным выбором в средах со слабым подключением к Интернету .
С другой стороны, алгоритм Hi/Lo не является лучшим выбором в средах, где несколько разных клиентов сохраняют данные в одной и той же таблице в базе данных . Сторонние приложения могут не знать о стратегии Hi/Lo, которую мы используем для создания идентификаторов. В результате они могут использовать идентификаторы сущностей из сгенерированного диапазона чисел, используемых в настоящее время в нашем приложении. В этом случае при сохранении данных мы можем столкнуться с ошибками, которые трудно исправить.
5. Заключение
В этом уроке мы обсудили алгоритм Hi/Lo.
Во-первых, мы объяснили, как это работает, и обсудили его реализацию псевдокода. Затем мы показали практический пример с использованием реализации алгоритма Hibernate. Наконец, мы перечислили преимущества и недостатки Hi/Lo.
Как всегда, код, показанный в этой статье, доступен на GitHub .