NHibernate:对象层次结构和性能

时间:2013-03-11 12:24:57

标签: c# nhibernate queryover

我有一个带有Customer表的数据库。这些客户中的每一个都具有安装表的外键,该表还具有地址表的外键(为简单起见,表重命名)。

NHibernate 中我试图像这样查询Customer表:

ISession session = tx.Session;
var customers = session.QueryOver<Customer>().Where(x => x.Country == country);                               
var installations = customers.JoinQueryOver(x => x.Installation, JoinType.LeftOuterJoin);
var addresses = installations.JoinQueryOver(x => x.Address, JoinType.LeftOuterJoin);

if (installationType != null)
{
    installations.Where(x => x.Type == installationType);
}

return customers.TransformUsing(new DistinctRootEntityResultTransformer()).List<Customer>();

导致SQL查询类似于(由NHibernate Profiler捕获):

SELECT *
FROM   Customer this_
       left outer join Installation installati1_
         on this_.InstallationId = installati1_.Id
       left outer join Address address2_
         on installati1_.AddressId = address2_.Id
WHERE  this_.CountryId = 4
       and installati1_.TypeId = 1

当我在 Microsoft SQL Server Management Studio 中执行上述SQL查询时,它会在大约5秒内执行,但会返回~200.000条记录。然而,在运行代码时需要花费大量时间来检索 List 。我已经等了10分钟没有任何结果。 debug-log指示由于对象层次结构而构造和启动了许多对象。有没有办法解决这个性能问题?

2 个答案:

答案 0 :(得分:1)

我不确定你要做什么,但是通过任何OR映射器加载和保存200000条记录是不可行的。 200000个对象将占用大量内存和时间。根据您要执行的操作,将它们加载到页面中或直接在数据库(sp或命名查询)上进行更新查询可以修复您的性能。批处理可以通过以下方式完成:

criteria.SetFirstResult(START).SetMaxResult(PAGESIZE);

答案 1 :(得分:0)

NHibernate Profiler在持续时间列x / y中显示两次,其中x是执行查询的时间,y是初始化对象的时间。第一步是确定问题所在。如果查询速度很慢,请使用SQL事件探查器(假设SQL Server)将实际查询发送到数据库,并检查其在SSMS中的性能。

但是,我怀疑您的问题可能是日志记录级别。如果您将日志记录级别设置为DEBUG,NHibernate将生成非常详细的日志,这将显着影响性能。

即使您可以使用200000条记录来表现良好,这些记录超出了您可以以有意义的方式向用户显示的记录。您应该使用分页/过滤来减小结果集的大小。