NHibernate:对象层次和性能

本文关键字:性能 层次 对象 NHibernate | 更新日期: 2023-09-27 18:03:31

我有一个带有Customer表的数据库。这些客户中的每一个都有一个指向Installation表的外键,而该表又有一个指向Address表的外键(为了简单起见,表已重命名)。

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>();

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

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条记录。然而,在运行代码时,检索列表需要花费大量时间。我已经等了十分钟了,没有任何结果。调试日志表明,由于对象层次结构,构造和初始化了许多对象。有办法解决这个性能问题吗?

NHibernate:对象层次和性能

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

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

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

然而,我怀疑你的问题可能是日志级别。如果你将日志级别设置为DEBUG, NHibernate将生成非常详细的日志,这将显著影响性能。

即使你能让它在200000条记录下运行良好,你也无法以一种有意义的方式显示给用户。您应该使用分页/过滤来减小结果集的大小。