2

我有一个 NHibernate 查询(正在填充 EXTJS 网格)

它向数据库发出 2 个查询,一个用于获取记录计数(用于分页目的),另一个用于获取前 N 行以填充网格。

从代码中,我一直在 Select count(*) 语句中遇到异常。

NHibernate.Exceptions.GenericADOException: 
Failed to execute multi criteria[SQL: 
 SELECT count(*) as y0_ FROM RecordView this_ inner join ProcessesView 
 process1_ on this_.ProcessId=process1_.Id inner join BusinessModelsView 
 businessmo3_ on process1_.BusinessModelId=businessmo3_.Id inner join BatchesView
 batch2_ on this_.BatchId=batch2_.Id WHERE this_.ProcessId = ?;
] ---> System.Data.SqlClient.SqlException: Timeout expired.  
The timeout period elapsed prior to completion of the operation or the server 
is not responding.

但是,如果我采用该确切查询并将其放入 SSMS 窗口并运行它,它会在 <1 秒内执行。

NHibernate 在这里做了什么“有趣”的事情。是否存在执行计划/缓存问题。我完全不知道为什么会发生这种情况。

4

2 回答 2

2

每当我遇到此错误时,原因是锁定从不执行)。有两个会话打开(意外)。两者都开始了事务,其中一个锁定了表。

问题可能是一些未处理的会话,或“意外”单例...持有已打开的会话。

这个答案并不像我希望的那样直截了当,但我对方向很有把握。因为我也有同样的经历(并且有罪)

顺便说一句:正如 Oskar Berggren 从你那里发现的那样,30 秒超时将与<property name="command_timeout">30</property>. 我敢肯定,如果您提供 60、120 ......由于锁定,这将是不够的

于 2013-08-23T03:50:25.870 回答
1

SQL SERVER 处理您的两个查询的方式不同

  • 您的 NH 查询已在第一次执行时根据表统计信息和参数的第一个值进行编译。生成的查询计划将用于所有后续调用,而不考虑参数值

  • 您的 SQL 查询(我猜,您将 ? 替换为实际值)根据统计信息和值对每个值进行不同的编译。

您的第一次 NH 编译可能已经生成了一个查询计划,对第一个值有效,但在一般情况下并非如此。

首先,我建议:

  • 你指望一个投影(比如在主表 id 上),因为它比 count(*) 稍微有效一些,允许数据库在可能的情况下只在索引上工作
  • 您检查您是否没有错过查询所需的任何索引
  • 您检查所有表格统计信息是否都是最新的

如果这不能提高执行时间,这篇文章提供了一些选项(重新编译可能是一个不错的选择): 从 Nhibernate 执行的查询很慢,但从 ADO.NET 执行的查询很快

于 2013-08-22T15:08:33.613 回答