Hibernate Subselect vs Batch Fetching
Hibernate предоставляет (как минимум) два варианта решения проблемы N+1. Один из них устанавливает FetchMode на Subselect, который генерирует выбор с предложением IN и выбором внутри этого предложения IN. Другой - указать BatchSize, который генерирует выбор с предложением IN, содержащим идентификаторы родителей.
Оба работают, но я обнаружил, что опция Subselect часто сталкивается с проблемами производительности из-за сложного запроса для родителей. С другой стороны, с большим BatchSize (скажем, 1000) количество запросов и сложность этих запросов очень малы.
Мой вопрос таков: когда бы вы использовали Hibnate-Subselect FetchMode вместо BatchSize? Суб-выбор, вероятно, имеет смысл, если у вас очень большое количество родительских записей (тысяч), но есть ли другие сценарии, в которых вы бы предпочли суб-выбор BatchSize?
РЕДАКТИРОВАТЬ: я заметил разницу между этими двумя при работе с нетерпением загрузки. Если у вас есть ассоциация xToMany, загружаемая с энтузиазмом и через подвыбор, она генерирует подвыбор, как если бы она была ленивой. Однако, если вы укажете BatchSize, сгенерированный запрос использует внешнее соединение, а не отдельный запрос. Есть ли способ заставить Hibernate использовать отдельный пакетный запрос при загрузке с нетерпением?
2 ответа
Я не использую подвыбор, потому что это трудно контролировать. В очень большой системе, которая имеет сложную бизнес-логику и над ней работает большая команда, слишком сложно сказать, какие запросы используются. Подвыбор может работать в определенных случаях, когда вы точно знаете, какой запрос выполняется.
Пакетная загрузка имеет несколько больших преимуществ. Это не всегда самый быстрый, но обычно достаточно быстрый. С другой стороны, он очень стабилен, не имеет побочных эффектов и полностью прозрачен для бизнес-логики. Я никогда не использую пакетные значения выше 100. Достаточно уменьшить N+1 до некоторого разумного количества запросов.
Я нашел эту статью полезной. Я считаю, что пакетная выборка может быть применена как к коллекции, так и к родительскому элементу, в то время как выборка может применяться только к коллекции.
В случае стратегии выборки для коллекций подвыбор будет выполняться один раз (поскольку размер пакета фактически равен бесконечности), тогда как при пакетной выборке оператор SQL может выполняться несколько раз.