6

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

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

如果有任何区别,我正在使用 Memcached.... 对于查询密集型系统,L2 缓存有更好的选择吗?

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

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

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

4

3 回答 3

5

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


我以前的答案(可能仍然有用)

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

要正确使用它,您应该

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

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

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

希望它清理森林...

于 2009-12-28T17:20:47.453 回答
1

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

于 2009-12-18T01:35:21.430 回答
0

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

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

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

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

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

于 2009-12-21T06:57:02.707 回答