首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NHibernate SysCache2和查询缓存-无法避免选择N+1?

NHibernate SysCache2和查询缓存-无法避免选择N+1?
EN

Stack Overflow用户
提问于 2013-01-07 17:48:53
回答 1查看 1.3K关注 0票数 2

我在Fluent NHibernate中使用二级缓存提供程序SysCache2,使用标准fluent配置(按照一般建议启用了查询缓存),并以通常的方式定义了基于表的依赖关系。

流利:

代码语言:javascript
复制
config.Cache(c => c
 .ProviderClass<NHibernate.Caches.SysCache2.SysCacheProvider>()
 .UseQueryCache()
 .UseSecondLevelCache()
 .UseMinimalPuts()

)

Web.Config:

代码语言:javascript
复制
  <cacheRegion name="User" relativeExpiration="7200">
<dependencies>
  <tables>
    <add name="User" databaseEntryName="OldClient" tableName="tbl_users" />
  </tables>
</dependencies>

用户映射:

代码语言:javascript
复制
public class UserMap : ClassMap<User>
{
    public UserMap()
    {
        Table("Users");
        ....
        // caching
        Cache.IncludeAll().ReadWrite().Region("Users");
    }
}

对于单个请求,一切都按预期运行,即:

代码语言:javascript
复制
Session<User>.Get()

正如从NHibernate caches by ID的方式所期望的那样。后续请求不会命中数据库,而使数据库中的记录无效会导致实体无效,从而导致在下一次请求期间调用后续SQL。一切都好。

问题出在查询缓存上。首先,一切都运行得很好。执行调用,例如:

代码语言:javascript
复制
Session<User>.Query(item => item.Active == true) 

如您所料,结果是SQL调用(SELECT * FROM Users WHERE Active = true)。并且随后的执行不会产生SQL。太棒了。直到查询集中的单个记录在数据库中被改变时为止。执行相同的查询,然后生成一个SELECT N+1:

代码语言:javascript
复制
SELECT * FROM Users WHERE ID = 1
SELECT * FROM Users WHERE ID = 2
SELECT * FROM Users WHERE ID = 3
SELECT * FROM Users WHERE ID = 4
...

我在其他地方找到了对此的引用,尽管没有解决方案:

StackOverflow - How do I make NHibernate cache fetched child collections?请参阅“更多一点”部分

Ayende Caching Strategies他在结尾提到要确保实体也被缓存

目前我可以避免这种情况的唯一方法是在每次请求后清除查询缓存-这几乎使它变得无用。当特定实体失效时,我需要让查询缓存清除该实体的所有内容-而不仅仅是单个记录。

有什么想法吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-07 18:21:41

根据您发布的两个链接,查询缓存将缓存查询结果的in,并开始逐个获取实体:如果缓存中有这些in,那么很好,如果没有,那么您现在有很多selects。

在这一点上,我假设您选择的实体不在二级缓存中(还在吗?)。我从来没有使用过基于表的依赖关系,我们使用的是command based dependencies,我只是测试了一下,如果一个实体被标记为无效,那么只有这个缓存的实体,而不是整个缓存区域,会被抛出缓存。

检查配置以确保它是正确的,也许当你认为你正在命中二级缓存时,你实际上正在命中会话缓存?请确保您正在测试缓存是否跨不同的会话工作。

在任何情况下,我建议您查看NHibernate的调试级日志,看看二级缓存实际发生了什么,在那里您将能够看到所有缓存命中/未命中。我可以给您的另一个技巧是在您的配置中启用generate_statistics标志。流利:

代码语言:javascript
复制
config.ExposeConfiguration(c => c.SetProperty("generate_statistics", "true"));

之后,您可以访问会话工厂中感兴趣的数据,如Session.SessionFactory.Statistics.SecondLevelCacheMissCountSession.SessionFactory.Statistics.SecondLevelCacheHitCount。结合使用这两种方法,您应该能够找出问题的原因。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/14193392

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档