Впадать в спящий режим:batch_size?Кэш второго уровня?
-
19-09-2019 - |
Вопрос
У меня есть объект домена Hibernate, который загружается разными частями приложения.Иногда выгодно лениво загружать каждую ассоциацию, а в других случаях лучше загрузить все целиком за одно объединение.В качестве, надеюсь, счастливого компромисса, который я нашел:
Используя пакетную выборку, Hibernate может загружать несколько неинициализированных прокси-серверов при обращении к одному прокси-серверу.Пакетная выборка - это оптимизация стратегии отложенной выборки.
hibernate.default_batch_fetch_size
:
Используя пакетную выборку, Hibernate может загружать несколько неинициализированных прокси при обращении к одному прокси.Пакетная выборка - это оптимизация стратегии отложенной выборки.
Я тоже вижу:
hibernate.jdbc.fetch_size
:
Ненулевое значение определяет размер выборки JDBC (вызывает оператор.setFetchSize()).
Хорошо, достаточно ли умен Hibernate, чтобы заглядывать в кэш второго уровня при выполнении пакетной выборки?т.е. выполняется ли одна выборка для первоначального вызова ассоциации, а затем следующие вызовы X попадают в кэш?Таким образом, я могу получать желаемую отложенную загрузку, но также часто обращаться к кэшу для более массовых транзакций.
Если все содержимое коллекции уже содержится в кэше, будет ли оно по-прежнему выполнять запросы на выборку при доступе к коллекции?
Спасибо.
Решение
Сегодня я провел много исследований и смог найти ответ на свой собственный вопрос.Я просматривал код гибернации, и поток выглядит следующим образом:
Инициализирована ли коллекция?
- Нет?Выполните пакетную выборку (элементы, полученные с помощью пакетной выборки, помещаются в кэш).
- Да?Поищите в кэше конкретный элемент, если его там нет, выполните пакетную выборку.
Таким образом, если элемент в коллекции, которую вы ищете, НАЙДЕН в кэше, то пакетная выборка не выполняется.Если элемент НЕ найден в кэше второго уровня, то выполняется пакетная выборка, НО она будет выполнять выборку пакетных элементов НЕЗАВИСИМО от того, находятся ли пакетные элементы в кэше.
----- ПРИМЕР 1 -----
Хорошее:
(Три предмета в коллекции - размер партии 3) Первый заход:
- collection.GetItem(0) - Нет кэша | пакетная выборка 3 элементов
- collection.GetItem(1) - Загружается с помощью пакетной выборки
- collection.GetItem(2) - Загружается с помощью пакетной выборки
Сейчас, где-нибудь в другом месте, позже по времени:
- collection.GetItem(0) - Попадание в кэш
- collection.GetItem(1) - Попадание в кэш
- collection.GetItem(2) - Попадание в кэш
----- ПРИМЕР 2 -----
Плохое:
(Три элемента в коллекции - размер пакета 3)
В этом случае элемент с индексом 0 был удален из кэша, потому что, возможно, кэш был заполнен и элемент был удален, или элемент устарел или простаивал.
- collection.GetItem(0) - Не в кэше, Поэтому сделайте пакет из 3 (выберите *, где id в (?, ?, ?))
- collection.GetItem(1) - Уже в кэше (в любом случае заменен на пакетную выборку)
- collection.GetItem(2) - Уже в кэше (в любом случае заменен на пакетную выборку)
Таким образом, компромисс здесь заключается в том, что у вас будет меньше SQL-вызовов из-за пакетной обработки, но вам будет чаще не хватать кэша.Открыт тикет, позволяющий просмотреть пакетную обработку в кэше второго уровня, прежде чем она отправится в базу данных.
http://opensource.atlassian.com/projects/hibernate/browse/HHH-1775
Голосуйте за это!