微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

查询在.Net SqlCommand.ExecuteNonQuery中超时,适用于SQL Server Management Studio

更新:问题解决了,并保持解决.如果您想查看该网站的运行情况,请访问 Tweet08

我有几个查询在SSMS中与在我的.Net应用程序中运行时的行为不同. SSMS在一秒钟内执行正常. .Net呼叫在120秒后超时(连接认超时).

我做了一个sql跟踪(并收集了一切)我已经看到连接选项是相同的(并匹配sql Server的认值).然而,SHOWPLAN All在行估计中显示出巨大的差异,因此工作版本会使用积极的表Spool,因为失败的调用没有.

在SSMS中,临时变量的数据类型基于.Net中生成sql参数,因此它们是相同的.

在VS2008调试会话中,Cassini下执行失败.成功归功于SSMS 2008.两者都在同一台计算机上的同一网络上运行相同的目标服务器.

在SSMS中查询

DECLARE @ContentTableID0 tinyint
DECLARE @EntryTag1 INT
DECLARE @ContentTableID2 tinyint
DECLARE @FieldCheckId3 INT
DECLARE @FieldCheckValue3 VARCHAR(128)
DECLARE @FieldCheckId5 INT
DECLARE @FieldCheckValue5 VARCHAR(128)
DECLARE @FieldCheckId7 INT 
DECLARE @FieldCheckValue7 VARCHAR(128)
SET @ContentTableID0= 3
SET @EntryTag1= 8
SET @ContentTableID2= 2
SET @FieldCheckId3= 14
SET @FieldCheckValue3= 'igor'
SET @FieldCheckId5= 33
SET @FieldCheckValue5= 'a'
SET @FieldCheckId7= 34
SET @FieldCheckValue7= 'a'

SELECT COUNT_BIG(*)
FROM dbo.ContentEntry AS mainCE
WHERE GetUTCDate() BETWEEN mainCE.CreatedOn AND mainCE.ExpiredOn
AND (mainCE.ContentTableID=@ContentTableID0)
AND ( EXISTS (SELECT *
              FROM dbo.ContentEntryLabel
              WHERE ContentEntryID = mainCE.ID
              AND GetUTCDate() BETWEEN CreatedOn AND ExpiredOn
              AND LabelFacetID = @EntryTag1))
      AND (mainCE.OwnerGUID IN (SELECT TOP 1 Name
                                FROM dbo.ContentEntry AS innerCE1
                                WHERE GetUTCDate() BETWEEN innerCE1.CreatedOn AND innerCE1.ExpiredOn
                                AND (innerCE1.ContentTableID=@ContentTableID2
                                     AND EXISTS (SELECT *
                                                 FROM dbo.ContentEntryField
                                                 WHERE ContentEntryID = innerCE1.ID
                                                 AND (ContentTableFieldID = @FieldCheckId3
                                                      AND DictionaryValueID IN (SELECT dv.ID
                                                                                FROM dbo.DictionaryValue AS dv
                                                                                WHERE dv.Word LIKE '%' + @FieldCheckValue3 + '%'))
                                                )
                                    )
                               )
           OR EXISTS (SELECT *
                      FROM dbo.ContentEntryField
                      WHERE ContentEntryID = mainCE.ID
                      AND (   (ContentTableFieldID = @FieldCheckId5
                               AND DictionaryValueID IN (SELECT dv.ID
                                                         FROM dbo.DictionaryValue AS dv
                                                         WHERE dv.Word LIKE '%' + @FieldCheckValue5 + '%')
                              )
                           OR (ContentTableFieldID = @FieldCheckId7
                               AND DictionaryValueID IN (SELECT dv.ID
                                                         FROM dbo.DictionaryValue AS dv
                                                         WHERE dv.Word LIKE '%' + @FieldCheckValue7 + '%')
                               )
                          )
                     )
          )

Trace的.Net调用版本(添加了一些格式):

exec sp_executesql N'SELECT COUNT_BIG(*) ...',N'@ContentTableID0 tinyint,@EntryTag1 int,@ContentTableID2 tinyint,@FieldCheckId3 int,@FieldCheckValue3 varchar(128),@FieldCheckId5 int,@FieldCheckValue5 varchar(128),@FieldCheckId7 int,@FieldCheckValue7 varchar(128)',@ContentTableID0=3,@EntryTag1=8,@ContentTableID2=2,@FieldCheckId3=14,@FieldCheckValue3='igor',@FieldCheckId5=33,@FieldCheckValue5='a',@FieldCheckId7=34,@FieldCheckValue7='a'

解决方法

它不是你的索引.

这是参数嗅探,因为它通常发生在参数化存储过程中.它甚至在那些了解参数嗅探的人中也不为人所知,但是当你通过sp_executesql使用参数时也会发生这种情况.

您将注意到,您在SSMS中测试的版本和分析器显示的版本不相同,因为分析器版本显示您的.Net应用程序正在通过sp_executesql执行它.如果您提取并执行实际为您的应用程序运行的完整sql文本,那么我相信您将在同一查询计划中看到相同的性能问题.

仅供参考:不同的查询计划是参数嗅探的关键指标.

FIX:解决这个问题的最简单方法是假设它在sql Server 2005或2008上执行,则添加子句“OPTION(RECOMPILE)”作为SELECT语句的最后一行.预先警告,您可能必须在它工作之前执行两次它并不总是在sql Server 2005上工作.如果发生这种情况,那么您可以采取其他步骤,但它们涉及的更多一些.

您可以尝试的一件事是检查并查看是否已为您的数据库打开“强制参数化”(它应该位于“选项”页面下的SSMS数据库属性中).要修改强制参数化,请执行以下命令:

ALTER DATABASE [yourDB] SET  ParaMETERIZATION SIMPLE

原文地址:https://www.jb51.cc/mssql/76960.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐