@BatchSize умное или глупое использование?

Сначала я объясню, как я понял и использую @BatchSize : @BatchSize для загрузки отношений объектов в пакетном режиме, делая меньше запросов SQL к базе данных. Это особенно полезно для LAZY @OneToMany отношений.

Однако это даже полезно в отношении LAZY @OneToOne и @ManyToOne : если вы загружаете список сущностей из базы данных и запрашиваете загрузку lazyed объекта @*ToOne , он будет загружать объекты @*ToOne , даже если я просто использую тест, который загружает отношение 1-го объекта списка.

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

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

Итак, давайте перейдем к главному.

Предположим, что я делаю все возможное, чтобы никогда не выполнять пост-фильтрующие операции, даже если это заставляет меня выполнять собственные SQL-запросы или использовать объекты DTO для запроса критериев выбора и т. Д.

  1. Правильно ли я считаю, что я могу просто @BatchSize каждые lazyed отношения после того, как тщательно подумали об использовании нетерпеливой загрузки / присоединения и, наконец, выбрать ленивое отношение?
  2. У меня есть интерес к поиску адекватного значения для @BatchSize или я могу подумать «чем больше, тем лучше»? Это означает, что «существует ли какой-либо предел числа в операторе« IN »SQL, который может сделать мой запрос достаточно медленным, чтобы он не стоил больше? Я использую Postgres, но если у вас есть ответы на другие вопросы, которые мне тоже интересны, я тоже заинтересован.
  3. Необязательный вопрос: кажется, что использование @BatchSize в classе не дает много результатов. Мне все равно приходится комментировать все ленивые отношения, я что-то пропустил или это бесполезно?

EDIT: Точка моего 3 заключается в том, что я получаю другое поведение.

Скажем, я загружаю список сущностей classа «A», у которого отношение LAZY OneToMany к B. Теперь я хочу напечатать все createDate из B. Так что я делаю classический цикл 2 для цикла.

Я теперь аннотировал B с BatchSize:

  • @OneToMany не аннотируется с BatchSize: каждый набор B загружается на каждой итерации независимо без пакетной обработки. Таким образом, моя аннотация в classе B, кажется, полностью игнорируется. Даже если я установил значение «два», и у меня есть 6 записей в одном наборе, у меня есть один запрос для этого набора.
    • @OneToMany аннотируется: у меня есть конкретный запрос загружаемых партий. Если я исправлю размер партии до двух, и у меня будет всего 10 B accros, я просто получаю 5 запросов: независимо от числа A i. Если я установил его в 100: у меня есть 1 запрос для объектов B.

PS: Я не рассматриваю какой-либо связанный запрос с B, который мог бы запустить загрузку полей B с выбором / подбором выборки.

EDIT 2: я только что нашел этот пост. Почему бы мне не использовать @BatchSize для каждого ленивого загруженного отношения? Хотя я googled и поиск на SO, прежде чем мой вопрос, думаю, я не использовал правильные слова …

Однако я добавляю что-то другое, что может привести к другому ответу: когда мне интересно об использовании BatchSize для каждого отношения, он выбирает, хочу ли я желать загрузки, с помощью join / select fetch или если мне нужна ленивая загрузка.

  1. Да, @BatchSize предназначен для использования с ленивыми ассоциациями.
  2. В любом случае Hibernate будет выполнять несколько операторов в большинстве ситуаций, даже если количество неинициализированных прокси / коллекций меньше заданного размера партии. См. Этот ответ для получения более подробной информации. Кроме того, более легкие запросы по сравнению с менее крупными могут положительно влиять на общую пропускную способность системы.
  3. @BatchSize на уровне classа означает, что указанный размер партии для объекта будет применяться для всех @*ToOne ленивых ассоциаций с этим объектом. См. Пример с объектом Person в документации .

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

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

Например, предположим, что у вас есть следующий объект, для которого bs и cs всегда используются, когда используется A

 public class A { @OneToMany private Collection bs; @OneToMany private Collection cs; } 

С нетерпением загружая bs и cs очевидно, страдает от N + 1, выбирает проблему, если вы не присоединяете их в одном запросе. Но если вы присоединитесь к ним в одном запросе, например, например:

 select a from A left join fetch a.bs left join fetch a.cs 

то вы создаете полное декартово произведение между значениями bs и cs и count(a.bs) x count(a.cs) в наборе результатов для каждого a которые читаются один за другим и собираются в сущности A и их коллекции bs и cs .

Пакетная выборка была бы очень оптимальной в этой ситуации, потому что сначала вы должны прочитать A s, затем bs а затем cs , что приведет к большему количеству запросов, но с гораздо меньшим количеством данных, которые передаются из базы данных. Кроме того, отдельные запросы намного проще, чем большие, с объединениями, и проще выполнять и оптимизировать базу данных.

  • Тип данных Postgres JSON Rails
  • Ошибка при получении: Ошибка аутентификации сверстников для пользователя «postgres» при попытке заставить pgsql работать с рельсами
  • Как передать пароль на pg_dump?
  • Драйвер JDBC PostgreSQL с Android
  • PostgreSQL «Столбец не существует», но на самом деле он
  • Создание UUID в инструкции Postgres for Insert?
  • Динамически создавать столбцы для кросс-таблицы в PostgreSQL
  • Какую версию PostgreSQL я запускаю?
  • Как я могу использовать UTF-8 в Linux из Windows 7 через PuTTY?
  • psql: FATAL: роли "postgres" не существует
  • Копирование базы данных PostgreSQL на другой сервер
  • Давайте будем гением компьютера.