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

时间:2011-10-13 11:46:50

标签: sql-server performance nhibernate ado.net

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

我在SO上遇到过类似问题的类似问题,所以我将我的测试更进了一步。

我使用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");

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

另外,我在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

4 个答案:

答案 0 :(得分:8)

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

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

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

DBCC FREEPROCCACHE -- clears the query-plan cache

再次快速查询。

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

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

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

答案 1 :(得分:6)

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

update statistics tablename;

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

答案 2 :(得分:2)

查看提供给sp_executesql存储过程的参数。如果参数以nvarchar(N'value')的形式提供,并且它们引用的列是varchar,则SQL Server将使用效率非常低的查询计划。这是我遇到的所有性能问题的根本原因,这些问题表现出这些症状(应用程序速度慢,SSMS速度快)。

答案 3 :(得分:0)

您没有指定查询或其结果集的大小,但是使用nHibernate获取大量实体时存在问题。
基本上,“保湿”物体的时间就是这么长的时间 您可以尝试打开反射优化器,或使用IStatelessSession 看到我有here的som建议。