优化 NHibernate 查询

Posted

技术标签:

【中文标题】优化 NHibernate 查询【英文标题】:Optimize NHibernate Query 【发布时间】:2009-05-13 07:33:26 【问题描述】:

在我的系统中,我对包含大量集合的聚合进行集中计算。我需要在计算之前加载所有集合,因此我使用一个多标准来连接根上的集合。

我在下面列出的标准。在我的本地设置上运行大约需要 500 毫秒,这需要用户等待很多。有人对我如何优化这个有任何想法吗?任何可以使此查询更快的帮助都将不胜感激!

(为了一点隐私,我更改了集合的名称:))

IMultiCriteria criteria = session.CreateMultiCriteria()
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("ACollection", JoinType.LeftOuterJoin)
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("BCollection", JoinType.LeftOuterJoin)
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("CCollection", JoinType.LeftOuterJoin)
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("ECollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("FCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("GCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("HCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("JCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("KCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("LCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("MCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("NCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("OCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("PCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("QCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("RCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("SCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("TCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("UCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("VCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("WCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("XCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("YCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("ZCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("AACollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("ABCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("ACCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("ADCollection", JoinType.LeftOuterJoin))
.Add(DetachedCriteria.For<Building>()
     .Add(Restrictions.Eq("Id", BuildingId))
     .CreateCriteria("AECollection", JoinType.LeftOuterJoin));

【问题讨论】:

呵呵...是的,我当然希望我有另一个选择! :) 【参考方案1】:

一段时间后,我终于意识到,对于这种确切的场景,使用像 MongoDB 这样的面向文档的数据库或对象数据库可能更有意义。

这样我就可以一次性加载整个聚合而忘记连接。

因此,对于遇到上述情况的任何人,请考虑使用面向文档的方法。

我的初步测试显示出有希望 :)

MongoDB 的介绍可以在这里找到:http://mookid.dk/oncode/archives/1057

【讨论】:

【参考方案2】:

我可以推荐的第一件事是启动您的 Sql Profiler 并获取传入的 sql 的精确副本。然后我会将其放入 Sql Tuner 中,这很可能会建议创建新索引以及添加/更新部分或全部表的统计信息。

此时我将运行性能测试,然后再尝试对 HQL 进行性能调整。

【讨论】:

以上是关于优化 NHibernate 查询的主要内容,如果未能解决你的问题,请参考以下文章

优化 NHibernate 查询

您是不是会将 NHibernate 用于具有部分无法控制的遗留数据库的项目?

NHibernate查询优化的相关资料

Linq To Nhibernate 性能优化(入门级)

如何让 NHibernate 停止使用 nvarchar(4000) 插入参数字符串?

C#中,某一多属性类的排序该如何实现?不用LinQ。