NHibernate SQL查询速度慢

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中执行它并立即获得结果.

你认为这种差异来自哪里?

Ste*_*ger 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; 
Run Code Online (Sandbox Code Playgroud)

如果确实刷新问题,则需要在事务中的某些点上手动刷新。关闭自动冲洗时要小心。它可能会导致丑陋的副作用。它对于您的交易来说非常具体,我无法告诉您如何以正确的方式实施它。您也可以使用 a StatelessSession,但对我来说它从来没有起作用(它有一些限制)。您还可以清除会话,这也要求您确切地知道自己在做什么。

如果不是冲水问题,就很难追踪。使用Profiler查看SQL Server查询是否实际花费了时间。甚至可能是 SQL Server 上的缓存问题。在这种情况下,第一次执行查询需要几分钟的时间,但第二次只需要几秒钟。创建适当的索引可能会有所帮助。到这里我就不再猜测了...