Hibernate предоставляет (по крайней мере) два варианта решения проблемы с запросом N + 1. Один устанавливает FetchMode в Subselect, который генерирует выбор с помощью IN-предложения и подзаголовка внутри этого IN-предложения. Другой - указать BatchSize, который генерирует выбор с IN-предложением, содержащим идентификаторы родителей.Hibernate Subselect vs Batch Fetching
Оба работают, но я обнаружил, что опция Subselect часто сталкивается с проблемами производительности из-за того, что запрос для родителей является сложным. С другой стороны, при большом BatchSize (скажем 1000) количество запросов и сложность этих запросов очень малы.
Мой вопрос: таким образом, когда вы используете Subselect FetchMode Hibernate для BatchSize? Subselect, вероятно, имеет смысл, если у вас очень большое число родительских записей (тысячи), но есть ли другие сценарии, где вы предпочитаете Subselect to BatchSize?
EDIT: Я заметил разницу между ними при работе с нетерпением. Если у вас есть установленная ассоциация xToMany, которая будет загружаться с нетерпением и с помощью подзапроса, она генерирует такой подселек, как если бы она была ленивой. Однако если вы укажете BatchSize, сгенерированный запрос использует внешнее соединение вместо отдельного запроса. Есть ли способ заставить Hibernate использовать отдельный пакетный запрос при загрузке с нетерпением?
Я не понимаю, почему подзапрос трудно контролировать. Можете ли вы проливать свет? –
Subselect зависит от запроса, который был выполнен ранее. Этот запрос может быть очень сложным, например. используя множество других таблиц и фильтрацию неиндексированными столбцами. Поэтому трудно сказать, может ли подход подзапроса повысить производительность. –
Еще одна проблема с подзапросом может возникнуть с MySQL; MySQL (5.5 и ниже) имеет ужасную производительность с вложенными запросами, поскольку он принудительно делает их коррелированными и переоценивает их для каждой строки в родительском запросе. Я не могу найти другого способа для Hibernate генерировать вложенный запрос для аннотированных отношений, поэтому избежать подзапроса предотвратит неприятный сюрприз MySQL. –