Как работает алгоритм пакетной выборки Hibernate?

Я нашел это описание алгоритма пакетной выборки в "Manning - Java Persistence with Hibernate":

Каков настоящий алгоритм пакетной выборки? (...) Представьте, что размер пакета равен 20, а общее количество 119 неинициализированных прокси должно быть загружено в пакетном режиме. Во время запуска Hibernate считывает метаданные сопоставления и создает 11 пакетных загрузчиков внутри. Каждый загрузчик знает, сколько прокси-серверов он может инициализировать: 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1. Цель состоит в том, чтобы минимизировать потребление памяти для создания загрузчика и создать достаточно загрузчиков, чтобы каждый возможна пакетная выборка. Другая цель, очевидно, минимизировать количество SQL-запросов. Для инициализации 119 прокси Hibernate выполняет семь пакетов (вы, вероятно, ожидали шесть, потому что 6 x 20 > 119). Применяемые пакетные загрузчики: пять раз по 20, один раз по 10 и один раз по 9, автоматически выбираемые Hibernate.

но я до сих пор не понимаю, как это работает.

  1. Почему 11 пакетных погрузчиков?
  2. Почему пакетные загрузчики могут инициализировать: 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 прокси?

Если бы кто-нибудь мог представить пошаговый алгоритм...:)

2 ответа

Решение

Я не смог найти в Интернете никакой информации о том, как hibernate справляется с пакетной загрузкой, но, судя по вашей информации, можно предположить следующее:

Почему 11 пакетных погрузчиков?

При размере пакета 20, если вы хотите минимизировать количество загрузчиков, необходимое для любой комбинации прокси-серверов, в основном есть два варианта:

  • создать загрузчик для 1,2,3,4,5,6,7,...20,21,22,23,... N неинициализированных прокси (глупо!) ИЛИ
  • создать загрузчик для любого N между 1..9, а затем создать больше загрузчиков для batch_size/2(Рекурсивно)

Пример: для пакета размером 40 вы получите загрузчики для 40,20,10,9,8,7,6,5,4,3,2,1.

  1. Если у вас есть 33 неинициализированных прокси, вы можете использовать следующие загрузчики: 20, 10, 3
  2. Если у вас 119 неинициализированных прокси, вы можете использовать следующие загрузчики: 40 (x2), 20, 10, 9
  3. ...

Почему пакетные загрузчики могут инициализировать: 20, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 прокси? Я думаю, что команда hibernate выбрала это как баланс между количеством загрузчиков, необходимых для загрузки "общего" числа N неинициализированных прокси, и потреблением памяти. Могли бы создать загрузчик для каждого N от 0 до batch_size, но я подозреваю, что загрузчики занимают значительное место в памяти, так что это компромисс. Алгоритм может быть примерно таким (обоснованное предположение):

  1. n = batch_size; while (n > 10)

    1.1. loader(n); n = n / 2

  2. for n = 0..10 create loader(n)

Это помогает избежать создания большого количества различных подготовленных заявлений.

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

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

Кроме того, поскольку жесткий анализ, как правило, очень дорогой, он обычно быстрее выполняет несколько подготовленных кэшированных операторов (включая несколько обращений к базе данных), чем анализирует и выполняет новый. Таким образом, помимо очевидного преимущества сокращения количества различных операторов, на самом деле может быть быстрее получить все 119 объектов путем выполнения 11 кэшированных операторов, чем создавать и выполнять один новый, который содержит все 119 идентификаторов.

Как уже упоминалось в комментариях, Hibernate вызывает ArrayHelper.getBatchSizes метод определения размеров партии для заданного максимального размера партии.

Другие вопросы по тегам