从Nhibernate执行的查询很慢,但是从ADO.NET开始很快

pso*_*usa 12 sql-server nhibernate performance ado.net

我在我的MVC应用程序中有一个查询,大约需要20秒才能完成(使用NHibernate 3.1).当我在Management studio上手动执行查询时,需要0秒.

我已经看到了类似于这个类似问题的类似问题,所以我进一步考虑了我的测试.

我使用Sql Server Profiler拦截了查询,并在我的应用程序中使用ADO.NET执行了查询.

我从Profiler获得的查询类似于:"exec sp_executesql N'select ...."

我的ADO.NET代码:

SqlConnection conn = (SqlConnection) NHibernateManager.Current.Connection;

var query = @"<query from profiler...>";
var cmd = new SqlCommand(query, conn);

SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
return RedirectToAction("Index");
Run Code Online (Sandbox Code Playgroud)

此查询也非常快,没有时间执行.

另外,我在Profiler上看到了一些非常奇怪的东西.从NH执行时,查询具有以下统计信息:

读取:281702写道:0

来自ADO.NET的那个:

读:333写:0

有人有任何线索吗?我可以提供任何信息来帮助诊断问题吗?

我认为它可能与某些连接设置有关,但ADO.NET版本使用的是NHibernate的相同连接.

提前致谢

更新:

我正在使用NHibernate LINQ.查询是巨大的,但是是一个分页查询,只提取了10条记录.

传递给"exec sp_executesql"的参数是:

@ p0 int,@ p1 datetime,@ p2 datetime,@ p3 bit,@ p4 int,@ p5 int

@ p0 = 10,@ p1 ='2009-12-01 00:00:00',@ p2 ='2009-12-31 23:59:59',@ p3 = 0,@ p4 = 1,@ p5 = 0

pso*_*usa 8

我有ADO.NET和NHibernate使用不同的查询计划,我更喜欢参数嗅探对NH版本的影响.为什么?因为我之前使用较小的日期间隔进行了查询,并且存储的查询计划已针对它进行了优化.

之后,当使用较大的日期间隔查询时,使用了存储的计划,并且需要很长时间才能得到结果.

我确认这实际上是问题,因为一个简单的:

DBCC FREEPROCCACHE -- clears the query-plan cache
Run Code Online (Sandbox Code Playgroud)

让我的查询再次快速.

我找到了两种方法来解决这个问题:

  • 使用NH拦截器向查询注入"选项(重新编译)"
  • 在我的NH Linq表达式中添加一个虚拟谓词,例如: query = query.Where(true)当预期的结果集很小时(明确的日期间隔).这样就可以创建两个不同的查询计划,一个用于大型数据集,另一个用于小型集.

我尝试了两种选择,两种方法都有效,但选择了第二种方法.它有点hacky,但我的情况非常好,因为数据是按日期统一分布的.

  • 我想指出“DBCC FREEPROCCACHE”清除整个缓存。这可能比你在一个有很多事情发生的系统(原文如此)中讨价还价要多。 (3认同)

Ski*_*ris 7

我有与OP完全相同的问题.我试着@psousa建议注入一个"选项(重新编译)",这确实提高了我的表现.但最后我发现简单地更新SQL Server的统计数据对我来说是个窍门.

update statistics tablename;
Run Code Online (Sandbox Code Playgroud)

我最终退出我的代码注入"选项(重新编译)".我意识到这可能不是每个人的答案,但想分享,因为这是我的问题的原因.