Hibernate кэш 2-го уровня в приложении Grails - PullRequest
38 голосов
/ 19 февраля 2012

Часть I

В приложении Grails я понимаю, что вы включаете кэш 2-го уровня для каждого класса домена, добавляя

static mapping {
  cache true
}

По умолчанию кэш 2-го уровня используется только при вызове get(), но его также можно использовать для запросов критериев и динамических искателей, добавив cache true к запросу.

Однако я все еще не уверен, что понимаю, как работает кэш запросов. Я думаю, что:

  • существуют отдельные кэши запросов для каждого класса домена, например, один для книги, другой для автора
  • перед выполнением запроса, подобного Author.findByName('bob', [cache: true]), вычисляется ключ кэша, который основан на классе домена (Author), запросе (findByName) и параметрах запроса ('bob'). Если этот ключ найден в кеше запросов автора, кэшированные результаты возвращаются вместо выполнения запроса
  • каждый раз, когда автор сохраняется, удаляется или обновляется, кэш запроса автора сбрасывается

Это кажется разумным, пока мы не посчитаем, что запрос, который возвращает экземпляры Book, может присоединиться к таблице Author. В этом случае необходимо будет очистить кэш запросов «Книга» и «Автор» при сохранении, удалении или обновлении автора. Это заставляет меня подозревать, что, возможно, существует только один кэш запросов, и он очищается всякий раз, когда сохраняется какой-либо класс кэшированных доменов?

Часть II

В документах Grails упоминается, что

Помимо возможности использовать кэш второго уровня Hibernate для кэширования экземпляров, вы также можете кэшировать коллекции (ассоциации) объектов.

Например:

class Author {    

  static hasMany = [books: Book]

  static mapping = { 
    cache true        // Author uses the 2nd level cache
    books cache: true // associated books use the 2nd level cache
  } 
}

class Book {
  static belongsTo = [author: Author]

  static mapping = {
    cache true // Book uses the 2nd level cache
  }
}

Имеет ли смысл приведенная выше конфигурация, т. Е. Если Автор и Книга сами используют кэш 2-го уровня, есть ли преимущество в том, что ассоциация Автор-Книга также использует кэш 2-го уровня?

Часть III

Наконец, я прочитал этот совет об использовании кэша запросов 2-го уровня, который предполагает, что его следует использовать только для нечасто меняющихся классов домена. Существуют ли обстоятельства, при которых нельзя включать кэш 2-го уровня для операций get(), т. Е. Какие-либо причины, по которым нельзя добавить следующее к классу домена

static mapping = {
  cache true // Book uses the 2nd level cache
}

1 Ответ

43 голосов
/ 21 февраля 2012

Часть 1:

Hibernate делает правильные вещи. Кеш запросов не для каждой сущности. Существует одна область кэша запросов, общая для всех запросов, если только вы не задали конкретную область для запроса. Каждый раз, когда таблица обновляется, ее метка времени в кэше меток времени обновляется. Каждый раз, когда выполняется запрос, временная метка каждой из таблиц, в которых выполняется поиск, сравнивается с временной меткой кэшированного результата. И, конечно же, кэшированный результат возвращается, только если его временная метка более поздняя, ​​чем все временные метки таблицы.

Часть 2:

Да, это имеет смысл. Кеш для автора помнит, что у автора с ID 456 есть имя «foo» и дата рождения 1975/07/19. Запоминаются только данные, хранящиеся в таблице автора. Таким образом, кэширование ассоциации также полезно: вместо выполнения дополнительного запроса для получения набора книг автора при вызове author.getBooks(), Hibernate получит идентификаторы книг автора из своего кэша, а затем загрузит каждую книгу из кэша второго уровня. Не забудьте кэшировать Книги, хотя.

Часть 3:

Я могу представить несколько причин:

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