NHibernate 二级缓存与多查询

发布于 2024-12-03 12:15:59 字数 299 浏览 1 评论 0原文

我们广泛使用 NHibernate 多查询功能并遇到奇怪的行为。似乎 NHibernate 不缓存多查询,它们总是访问数据库。我们使用 QueryOver,所有查询都设置为可缓存,但是当使用 blitz.io测试主页时-p 1-250:30 模式我可以看到,唯一命中数据库的多查询被执行了 2000 多次,而其他查询(例如选择当前登录的用户)仅执行一两次。

所以问题是:我是否遗漏了一些东西,或者 NHibernate 没有真正缓存多查询结果?

We're extensively using NHibernate multi-query functionality and experiencing strange behavior. Seems like NHibernate does not cache multiqueries and they always hit the database. We're using QueryOver, all queries are set to be cacheable, but when testing home page with blitz.io with -p 1-250:30 pattern I can see that the only multi-query that hits the database gets executed 2000+ times, whereas other queries (like selecting currently signed in user) are executed only once or twice.

So the question is: am I missing something or NHibernate does not really cache multi-query results?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

许久 2024-12-10 12:16:00

啊哈,明白了!事实证明,这并不全是二级缓存的错,而是我们对 QueryOver 的使用造成的。

当我们编写多租户 SaaS 应用程序时,我们的大多数查询如下所示:

return
    Session.QueryOver<Article>().Cacheable().
        Where(a => a.Site == site && a.PublishedAt <= publishedAt).
        OrderByCoalesceDesc(typeof(DateTime), a => a.UpdatedAt, a => a.CreatedAt).
        Take(count).
        Future();

a.Site == site 就是问题所在。显然,查询缓存检查查询结果是否被缓存的方式基本上是使用 SQL 语句和所有参数的组合作为缓存“哈希表”的键。对于我们的多个查询,SQL 语句文本始终相同,但 site 参数是罪魁祸首。 NH 检查所有提供的参数是否与缓存中已有的参数匹配,当然我们没有在 Site 类中实现 Equals(),因此检查总是失败。

我们最终的结果是重写我们的查询,如下所示:

var siteID = site.ID;
return
    Session.QueryOver<Article>().Cacheable().
        Where(a => a.Site.ID == siteID && a.PublishedAt <= publishedAt)...

Aha, got it! As it turned out, it was not all second-level cache's fault, but rather our usage of QueryOver is to blame.

As we're writing a multi-tenant SaaS application, most of our queries looked like this:

return
    Session.QueryOver<Article>().Cacheable().
        Where(a => a.Site == site && a.PublishedAt <= publishedAt).
        OrderByCoalesceDesc(typeof(DateTime), a => a.UpdatedAt, a => a.CreatedAt).
        Take(count).
        Future();

And a.Site == site was the problem. Apparently, the way query cache checks whether query results are cached or not is basically by using a combination of an SQL statement and all paramters as a key to the cache "hashtable". SQL statement text is always the same for our multi-queries, but the site parameter was the culprit. NH checks to see whether all supplied parameters match those already in cache and naturally we don't have Equals() implemented in our Site class, so the check always failed.

What we ended up with was rewriting our queries like this:

var siteID = site.ID;
return
    Session.QueryOver<Article>().Cacheable().
        Where(a => a.Site.ID == siteID && a.PublishedAt <= publishedAt)...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文