Cache de consulta de hibernação - para objetos que não estão no cache de segundo nível - arriscado?útil?má prática?

StackOverflow https://stackoverflow.com/questions/1998326

Pergunta

Relacionado a isso pergunta

Premissa:

Estas são minhas suposições, baseadas na minha leitura, experiência e compreensão, elas podem estar erradas, se estiverem, comente e eu editarei a pergunta.

  • O cache de consulta é bom principalmente junto com o cache de segundo nível
  • O cache de consulta armazena em cache os resultados dos identificadores das consultas + parâmetros
  • O cache de consulta é arriscado se o banco de dados foi alterado e não foi refletido no cache

Pergunta:

Tenho um objeto que não está no cache de 2º nível.Devido a alguma programação incorreta ou outras restrições, o código que carrega o objeto está sendo chamado diversas vezes na mesma sessão de hibernação.A recuperação está usando uma consulta HQL, por exemplo,

 hibernateTemplate.find("from Foo f where f.bar > ?", bar);

Antes de adicionar o cache de consulta, se o código acima fosse chamado N vezes na mesma sessão do Hibernate, haveria N ocorrências no banco de dados

Então eu queria ver o que acontece se eu adicionar cache de consulta:

 Query query = session.createQuery("from Foo f where f.bar > ?");
 query.setCacheable(true);
 query.setParameter(bar);
 query.list();

Quando adicionei o cache de consulta, percebi que durante a mesma sessão, o hibernate não atinge mais o banco de dados N vezes, apenas uma vez por sessão.

  1. Portanto, minha primeira suposição é que o Hibernate pesquisa primeiro no cache de sessão e depois no cache de segundo nível.Esta suposição está correta?
  2. Também presumo que se o objeto (Foo) que não está no cache de segundo nível, foi alterado no banco de dados, então o cache de consulta, com escopo de sessão cruzada, retornará os identificadores errados e, portanto, os objetos errados.Isso está correto?
  3. É então seguro dizer que usar o cache de consulta para consultas que incluem informações imutáveis, mesmo para objetos não armazenados em cache 2L, é uma boa prática?(por exemplo.uma consulta cuja cláusula where contém uma condição que sempre retornará os mesmos resultados, por exemplo."Selecione P.Ser_num onde p.id =?" Quando os casais ser_num e id não mudam uma vez criados)

A propósito, no relacionado pergunta afirma-se que o cache de consulta não funciona no escopo do Cache de Sessão.Estou entendendo mal essa afirmação ou qualquer outra coisa?

Foi útil?

Solução

Um cache de consulta é um tipo específico de cache de 2º nível. O que você chama de cache do 2º nível, eu prefiro chamar de "cache do objeto".

Comentários sobre suas suposições:

  • O cache de consulta é bom principalmente junto com o cache do 2º nível (também conhecido como cache de objeto).

Um cache de consulta mantém apenas os resultados brutos das consultas como chaves primárias, no hibernato falam, id. Ele não segura os objetos hidratados reais. Isso faz sentido, pois quando você executa uma consulta com o JDBC, ele realmente oferece objetos hidratados (povoados) à medida que você itera sobre o ResultSet. A declaração não está necessariamente correta. Se a consulta for muito complicada e, portanto, levar muito tempo para ser executada, usando um cache de consulta, você economizará esse tempo. Você não usará um cache de consulta, economize o tempo necessário para carregar os objetos do banco de dados.

  • O cache de consulta é arriscado se o banco de dados foi alterado e não foi refletido no cache

Isso é verdade, mas não é exclusivo do cache de consultas, o mesmo vale para o que você chama de cache de 2º nível, mas o que normalmente é chamado de cache de objeto.

Portanto, minha primeira suposição é que o Hibernate as primeiras pesquisas no cache da sessão e depois no cache do 2º nível. Esta suposição está correta?

Sim, ao carregar objetos, esse é o comportamento.

Presumo também que, se o objeto (foo) que não estiver no cache do segundo nível, foi alterado no banco de dados, o cache de consulta, sendo o escopo de sessão cruzada, retornará os identificadores errados e, portanto, os objetos errados. Isso está correto?

Sim, o cache do objeto e o cache de consulta serão afetados. Isso é apenas preocupante se o banco de dados for alterado sem passar por hibernado. Você pode potencialmente mitigar o efeito disso definindo o tempo limite do cache de consulta.

É seguro dizer que o uso de cache de consulta para consultas que incluem informações imutáveis, mesmo para objetos não em cache 2L, é uma boa prática? (Por exemplo, uma consulta de que a cláusula é que a cláusula contém uma condição que sempre retornará os mesmos resultados, por exemplo, "Selecione P.Ser_num onde p.id =?" Quando os casais ser_num e id não mudam uma vez criados)

Para esse tipo de objetos, não há razão para não usar um cache de objeto e um cache de consulta.

E sim, o Cache de consulta não funciona no nível da sessão, também conhecido como cache de nível 1. Assim, o motivo pelo qual você executa a consulta novamente, ela atinge o banco de dados novamente. Ele não colocará o resultado (conjunto de identificação) de uma consulta no cache da sessão.

Outras dicas

apenas suposições:

De acordo com isso artigo da documentação do Hibernate:

Cache de consulta] Cria duas novas regiões de cache:Um dos conjuntos de resultados de consulta em cache (org.hibernate.cache.standardQuerycache), os outros registros de data e hora das atualizações mais recentes das tabelas consultáveis ​​(org.hibernate.cache.updateTimestampscache).

Suponho que isso significa que sempre que o carimbo de data/hora da tabela consultável for mais recente que o conjunto de resultados - isso fará com que o hibernate se aproxime do banco de dados na próxima chamada para essa consulta, e é isso que mantém o cache de consulta seguro em algum aspecto.

Mas 2 frases depois no mesmo parágrafo da documentação diz:

O cache de consulta sempre deve ser usado em conjunto com o cache de segundo nível.

novamente, minha suposição é que esta é a única maneira pela qual o hibernate pode estar ciente das alterações no banco de dados que são feitas fora da sessão deste usuário específico

Para a sua pergunta nº 3, acho que você não quer usar o cache de consulta quando os objetos não estão em cache. Você acabará com todos os IDs primários, mas terá que atingir o banco de dados uma vez por chave para recuperar os objetos que podem ser mais lentos do que executar a consulta sem cache. De qualquer forma, a partir de 3.3, talvez em versões mais recentes, ele pega os objetos ausentes usando menos consultas, por exemplo, onde o ID em (: ID1 ,: ID2, ...).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top