Как работает алгоритм пакетной выборки Hibernate? - PullRequest
7 голосов
/ 12 августа 2010

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

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

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

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

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

Ответы [ 2 ]

5 голосов
/ 03 июля 2015

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

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

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

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

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

4 голосов
/ 09 июня 2011

Я не смог найти в Интернете никакой информации о том, как 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)

...