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 может выполняться несколько раз.

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