Hibernate Кэш запросов второго уровня не работает - PullRequest
6 голосов
/ 18 ноября 2009

В NHibernate Profiler я заметил, что, когда я использую активную выборку для ассоциации, используя «выборку из левого соединения» в HQL-запросе или .SetFetchMode () в запросе критериев, запрос больше не кэшируется в кеше запросов.

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

Если это имеет какое-то значение, я использую Memcached .... Есть ли лучший выбор для L2 Cache для системы с плотным запросом?

Я нахожу это довольно сложным - если я не использую нетерпеливую нагрузку, у меня проблема N + 1 (но использует кеш), если я загружаю энергично, я получаю все сущности из базы данных, но без кэширование.

Кажется, что есть довольно толстая разделительная линия, обе стратегии имеют улучшения производительности, но обе стратегии отнимают производительность у другой стратегии.

Если кто-то может дать какое-либо представление о том, где находится эта «толстая линия», я должен иметь оптимальную производительность или как «сделать линию тоньше» ... Я был бы очень осторожен и отметил бы ответ.

Ответы [ 3 ]

5 голосов
/ 28 декабря 2009

Обновление: Пожалуйста, смотрите мой связанный вопрос здесь . нижняя строка - попробуйте использовать fetch = "select", чтобы избежать объединения с объектами, которые уже находятся в кэше 2-го уровня.


Мой предыдущий ответ (все еще может быть полезным)

Кеш запросов кеширует идентификаторы, возвращаемые из вашего запроса, а не фактические объекты

Чтобы использовать его правильно, вы должны

  1. Использовать заполнители (? Или: varName)
  2. Установить кэш запроса в true (вы сделали)
  3. Запрос должен возвращать объекты, а не свойства (from Foo, а не select foo.bar from Foo foo)
  4. Возвращенные объекты должны находиться либо в кэше 2-го уровня, либо последующие вызовы находятся в том же сеансе гибернации (та же транзакция)

Чтобы уточнить # 4, если 2 разные транзакции запускают точный (кэшированный) запрос с точными параметрами и возвращают точно такой же объект, но он не находится в кэше 2-го уровня, все равно произойдет попадание в базу данных, чтобы получить действительный объекты (вероятно, избранные .. в)

Кэш запросов полезен для двух вещей - избегайте повторного попадания в базу данных в одной транзакции для запросов HQL для не кэшированных элементов и разрешите использовать кэшированные объекты 2-го уровня для запросов HQL (автоматически используется в командах load или get)

Надеюсь, это очистило лес ...

1 голос
/ 18 декабря 2009

Я не знаю о NHibernate, но в Hibernate вы должны явно включить кэширование запросов для подсказок использования запросов. Кэш L2 может автоматически кэшировать отдельные объекты, но для запросов это требует явных указаний.

0 голосов
/ 21 декабря 2009

Не совсем ответ - скорее подсказка ... И кеш сбора, и кеш запросов на самом деле не хранят результаты. Они просто хранят идентификаторы результирующих объектов. Это кэш сущности / класса, в котором хранятся данные сущности.

Итак, подумайте об этом - если запрос возвращает несколько типов сущностей (т. Е. Активную загрузку), он не может разумно хранить массив идентификаторов, поскольку между сущностями есть связь. Я считаю, что сам кеш имеет очень простую структуру.

Я не уверен насчет запросов 'value' - то есть таких, которые будут использовать проекции вместо классов. Я бы сказал, что вы не можете их кешировать. Но я могу ошибаться.

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

Надеюсь, это поможет (хотя бы немного).

...