当我尝试从数据库加载~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会话工厂,这不是性能问题的原因)
环境: nHibernate 3.3.1.4000,fnHibernate 1.3.0.733,MS SQL Server 2008,c#4.0,Windows 7-64。
答案 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。