我正在使用LINQ to NH来获取应用启动时的大量数据。我特意添加ToList()
以强制立即执行查询:
Group group = GetGroup();
Log.Info("started");
var list = Session.Linq<Data>()
.Where(p => p.Group.Id == group.Id)
.OrderByDescending(p => p.Stamp.Counter) /* Stamp is composite mapping */
.Select(p => new
{
Counter = p.Stamp.Counter,
Status = p.Status,
})
.Take(4000)
.ToList();
Log.Info("done");
检查NHibernate.SQL
logger的DEBUG日志会按预期提供以下SQL(当我开始监视时,SQL Profiler中会弹出相同的查询):
SELECT top 4000 this_.Counter as y0_, this_.Status as y1_
FROM [Data] this_
LEFT OUTER JOIN [Group] group1_ ON this_.Group_id=group1_.Id
WHERE group1_.Id = @p0
ORDER BY this_.Counter desc; @p0 = 1
问题是,从我的应用程序调用时,此查询需要2分钟才能完成,而在SSMS中执行则需要0.5秒!实际上,当应用程序等待查询完成时,我可以在SSMS中执行它并立即获得结果。
您认为这种差异来自哪里?
答案 0 :(得分:4)
由于关于您的应用程序的信息不多,我只能猜测。
NH的性能问题通常是由刷新缓存引起的。在每次查询之前刷新缓存。当会话中有很多实体时,可能需要花费很多时间。请尝试以下方法:
Log.Info("Flushing");
Session.Flush();
Session.FlushMode = FlushMode.Never;
Log.Info("Query");
var list = Session.Linq<Data>()
//...
Log.Info("Done");
// for production code, this belongs into a finally block
Session.FlushMode = FlushMode.Auto;
如果实际上 是一个刷新问题,则需要在事务中的某些点上手动刷新。关闭自动冲洗时要小心。它可能会导致丑陋的副作用。这是非常具体的交易,我不能说你如何以正确的方式实现它。您也可以使用StatelessSession
,但对我来说它从未奏效(它有一些限制)。您也可以清除会话,这也要求您确切知道自己在做什么。
如果没有冲洗问题,则很难跟踪。使用Profiler查看它是否实际占用SQL Server查询中的时间。它甚至可能是SQL服务器上的缓存问题。在这种情况下,第一次执行查询时需要几分钟,但第二次只需几秒钟。创建适当的索引可能有所帮在这里,我停止猜测...
答案 1 :(得分:3)
我的假设是有一些拦截器会减慢对象的实现或加载(即N + 1问题)。
我做了一些测试,甚至30 000个对象也无法减慢获取对象列表的速度(从本地机器500ms获取30000个对象的列表,从远程数据库 - 4秒)。
答案 2 :(得分:2)
有几个可能的原因:
这些来自我的头脑,还有我更多。另外检查NHibernate的日志级别是否未设置为DEBUG,它非常详细,可以消耗大量资源。
答案 3 :(得分:2)
今天一个项目的一个不错的观点:
我搜索了大约一周的原因,因为我的nHibernate查询(使用期货加载某些集合的多标准)需要11秒(在MSSQL探查器中持续时间),如果我在SSMS中执行完全相同的组合查询,则大约需要2秒。< / p>
解决方案是:我激活了一些日志来运行Ayendes profiler。 NHProf dll丢失了,但是:nHibernate中的一些GetRows方法在水合期间触发日志调用。差异是:9秒!
我刚刚注释掉了log4net配置调用,延迟几乎消失了。
我有大约14.000个实例加上60.000个HasMany集合条目。水合现在需要0.6秒,因为SQL语句需要2秒(这是另一个优化故事)。
并且:我认为水合持续时间和查询执行持续时间一起显示在SQL事件探查器“duration”列中。
2周前的另一个故事是:SQL分析器中的执行计划与在SSMS中执行查询时提供的执行计划不同。原因是,我在nHibernate中使用了OLEDB提供程序。我切换到ADO连接,执行计划是一样的。我在查看MS SQL分析器中的一些“协议版本”列时发现了这一点。
除了n + 1之外,性能陷阱有很多原因:)
祝福! 迈克尔