使用nHibernate选择具有许多子集合的实体的性能不佳

时间:2013-07-24 12:51:31

标签: .net nhibernate orm

当我尝试从数据库加载~7700条记录时,我正在处理的系统出现性能问题。与使用SqlDataReader的相同查询相比,NHB的加载时间要长10倍。显然使用NHB会有一些性能开销,但与ADO.NET相比,10倍的时间似乎过多。从我可以确定的,NHB是问题,特别是它如何处理挂起实体的集合。

当我们尝试加载大量(ish)数量的实体时,我们在整个系统中存在这个一般性问题,当实体本身有大量的集合挂起时。

我希望有人可以就如何改善这个问题提供一些建议。

查询很简单。

var employees = session.QueryOver<Employee>().List();

也没有发生选择n + 1 /延迟抓取问题。发布的单个DB语句实际上是select * from employee

我不会发布该实体的完整流畅映射,除非有人问,因为它非常大,但它相当标准。有问题的实体包括:

  

24个字段
  3 1-1关系
  86 1- *关系

提取物:

HasMany(e => e.Roles)
.Access.CamelCaseField(Prefix.Underscore)
.Cascade.AllDeleteOrphan()
.Fetch.Select()
.Inverse()
.LazyLoad()
.KeyColumns.Add("[EmployeeId]")
.Cache.ReadWrite().IncludeAll();

以下是执行1000次的5次测试的平均时间。当我创建/处置NHB会话时,计时开始/停止,它不包括创建会话工厂。

00:00:00.7080910 - 7677 records loaded/entity instantiation/manual map using ADO.NET
00:00:01.6055084 - 7677 entities - session - Fields Only
00:00:01.7866198 - 7677 entities - session - Fields + 1-1 Relationships
00:00:11.3384154 - 7677 entities - session - Fields + 1-1 Relationships + 1-* Relationships
00:00:10.9083002 - 7677 entities - stateless session - Fields + 1-1 Relationships + 1-* Relationships

为了清楚起见,这不是数据库/网络/延迟提取问题。国际海事组织的问题似乎在于NHB如何为实体提供水合作用。

编辑:即使fNHB映射指定了缓存,它也会在会话工厂中禁用。我明确地将它们从映射文件中删除以进行验证,并且持续时间不变。

我还使用ANTS来分析代码,似乎大部分时间花在TwoPhaseLoad.InitializeEntity上。 (忽略其他50%的时间,下面没有显示。它的nHibernates会话工厂,这不是性能问题的原因)

ANTS Performance Profile Capture

环境: nHibernate 3.3.1.4000,fnHibernate 1.3.0.733,MS SQL Server 2008,c#4.0,Windows 7-64。

1 个答案:

答案 0 :(得分:-1)

编写查询时,必须在IQueryable中包含.FetchMany(Func lambda)NHibernate扩展。

例如,如果您使用Bars查询一对多的Foos:

class Foo 
{
    IList<Bar> Bars
}

而不是

session.Query<Foo>().ToList();(全部)

你应该写

session.Query<Foo>().FetchMany( src => src.Bars ).ToList();

将告诉nhibernate获取连接而不是每行上的fetch select。