【问题标题】:Hibernate Second-Level Query Cache not working Eager FetchingHibernate 二级查询缓存不起作用急切获取
【发布时间】:2009-11-17 22:04:49
【问题描述】:

在 NHibernate Profiler 中,我观察到,当我对关联使用渴望获取时,在 HQL 查询中使用“左连接获取”或在条件查询中使用 .SetFetchMode(),查询不再缓存在查询缓存中。

事实上,据我所见,只有非常基本的查询被缓存。如果有人可以让我深入了解哪些查询会被缓存,哪些不会被缓存,我会标记答案。

如果有什么不同,我正在使用 Memcached.... 对于查询密集的系统,L2 缓存有更好的选择吗?

我发现这相当具有挑战性 - 如果我不使用预加载,我会遇到 N+1 问题(但使用缓存),如果我进行预加载,我会从数据库中获取所有实体,但没有缓存。

似乎有一条很粗的分界线,两种策略都有性能提升,但两种策略都从另一个策略中夺走了性能。

如果有人能深入了解这条“粗线”上的位置,我应该获得最佳性能,或者如何“使线更细”......我会非常关注并标记答案。

【问题讨论】:

  • 您的建议听起来不错,但我现在正在度假,我还没有机会尝试这个。我不记得我的查询是否有一个 select... 组件,这可能是我的问题的原因。我会试一试,然后再恢复。谢谢!
  • 用我的一个相关问题更新了我的答案,我认为它可能非常相关。

标签: java nhibernate caching hql query-cache


【解决方案1】:

更新: 请参阅我的相关问题here。底线是,尝试使用 fetch="select" 来避免加入已经在二级缓存中的对象。


我之前的回答(可能还有用)

查询缓存缓存从查询返回的标识符,而不是实际的对象

要正确使用它,你应该

  1. 使用占位符(? 或 :varName)
  2. 将查询缓存设置为 true(您这样做了)
  3. 查询应该返回对象,而不是属性(from Foo,而不是 select foo.bar from Foo foo
  4. 返回的对象应该在二级缓存中,或者后续调用在同一个休眠会话(同一个事务)中

为了澄清#4,如果 2 个不同的事务使用确切的参数运行确切的(缓存的)查询并返回完全相同的对象,但它不在 2 级缓存中,仍然会发生数据库命中以获取实际对象(可能是一个 select .. in )

查询缓存对两件事很有用 - 避免在同一事务中针对非缓存项目的 HQL 查询重新访问数据库,并允许将二级缓存对象用于 HQL 查询(自动用于加载或获取命令)

希望它能清理森林......

【讨论】:

    【解决方案2】:

    我不了解 NHibernate,但在 Hibernate 中,您必须为查询使用提示显式启用查询缓存。 L2 缓存可以自动缓存单个对象,但对于查询,它需要明确的指示。

    【讨论】:

    • 感谢您的回答。我正在启用查询缓存,但由于某种原因,每当我将“join fetch”添加到查询中时,缓存都不会被命中。
    【解决方案3】:

    不是一个真正的答案——而是一个提示......集合和查询缓存都不会真正存储结果。它们只存储结果实体的标识符。它是存储实体数据的实体/类缓存。

    所以考虑一下 - 如果查询返回多个实体类型(即急切加载),它不能合理地存储 id 数组,因为实体之间存在关系。我相信缓存本身的结构非常简单。

    我不确定“值”查询 - 即使用投影而不是类的查询。我会说你不能缓存这些。但我可能错了。

    现在虽然这可能对您的问题没有帮助 - 还有其他技术可以。即批量加载和适当的实体缓存。我会小心收集缓存。我被它们咬了好几次。

    希望能有所帮助(至少有点)。

    【讨论】:

      猜你喜欢
      • 2014-11-28
      • 2011-12-18
      • 1970-01-01
      • 1970-01-01
      • 2013-09-23
      • 1970-01-01
      • 2014-08-12
      • 2010-10-16
      • 1970-01-01
      相关资源
      最近更新 更多