Gro*_*roo 11 .net sql nhibernate
我正在使用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");
Run Code Online (Sandbox Code Playgroud)
检查NHibernate.SQL记录器的DEBUG日志会按预期提供以下SQL(当我开始监视时,在SQL事件探查器中弹出相同的查询):
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
Run Code Online (Sandbox Code Playgroud)
问题是,从我的应用程序调用时,此查询需要2分钟才能完成,而在SSMS中执行则需要0.5秒!实际上,当应用程序正在等待查询完成时,我可以在SSMS中执行它并立即获得结果.
你认为这种差异来自哪里?
由于您的申请信息不多,我只能猜测。
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;
Run Code Online (Sandbox Code Playgroud)
如果确实是刷新问题,则需要在事务中的某些点上手动刷新。关闭自动冲洗时要小心。它可能会导致丑陋的副作用。它对于您的交易来说非常具体,我无法告诉您如何以正确的方式实施它。您也可以使用 a StatelessSession,但对我来说它从来没有起作用(它有一些限制)。您还可以清除会话,这也要求您确切地知道自己在做什么。
如果不是冲水问题,就很难追踪。使用Profiler查看SQL Server查询是否实际花费了时间。甚至可能是 SQL Server 上的缓存问题。在这种情况下,第一次执行查询需要几分钟的时间,但第二次只需要几秒钟。创建适当的索引可能会有所帮助。到这里我就不再猜测了...