基于XML的查询通过ADO.NET非常慢,通过SSMS即时

时间:2012-03-27 14:36:06

标签: sql-server performance ssms

我处于常年的情况:一个查询通过一些读取立即通过SSMS运行,但是在通过ADO.NET运行时足够慢到超过数千次读取。 我在StackOverflow上可以找到的其他问题不同,清除查询缓存(或强迫自己使用SSMS使用的那个)似乎没有做到这一点。

通常,当其他人在StackOverflow上报告这种情况时,他们已经有了损坏的查询缓存。在所有这些情况下,修复程序要么使用SET ARITHABORT ON运行ADO.NET查询(以匹配SSMS使用的会话设置),要么运行DBCC DROPCLEANBUFFERSDBCC FREEPROCCACHE到强制查询缓存重建。这些技术在我的应用程序中没有任何区别,让我相信有一些更基本的东西。

有问题的查询是这样的(SQL Profiler捕获的实际逐字查询,仅为格式化而清理):

declare @p5 xml
set @p5=convert(xml,N'<r>
<n v="66ebc21b3bcb31e9a5ecbfb4b29fd2a47c37994c"/>
<n v="665919306fb23d9e685638a2d199e1e623745305"/>
<n v="a080c3b4e0c86e37b4d494d5efc09cebe20c6929"/>
<n v="245cb49bdeca9e37ef9bbd55877e21ade14e6282"/>
<n v="297650a6be65be332c1bb2aab426331a156ee342"/>
<n v="6a2668c8ab64fecf3b6925c7be613c61cef4dd7c"/>
<n v="09923f25f8b1de19f693bca1111bfa50d617856e"/>
<n v="0a7836d8e4e34f4ea92b2105eea5a99029949428"/></r>')
exec sp_executesql N'
            SELECT ixChangesetTag, ixRepo, ixChangeset, sTag, fBookmark
            FROM ChangesetTag
              INNER JOIN @p2.nodes(''/r/n'') X(n) ON X.n.value(''xs:hexBinary(@v)'', ''binary(20)'') = ixChangeset
            WHERE ixRepo = @p0 AND ixCustomer = @p1',N'@p0 bigint,@p1 int,@p2 xml',@p0=2,@p1=23363,@p2=@p5

(XML参数是为了允许使用参数化查询,我通常无法这样做,因为我想传入的对象数量各不相同。表值程序将是2008年的方法,但我们的一些客户在2005年运行。)

运行SSMS,使用的实际查询计划看起来合适(索引搜索),并且在4ms内读取大约200次。通过Web应用程序,一秒钟内读取大约需要4500次。

我在这里缺少什么?尽管进行了DBCC来电和ARITHABORT设置,但在通过网络应用程序运行时,是否可以恢复错误的查询计划?

2 个答案:

答案 0 :(得分:2)

简单修复就是在(ixCustomer,ixRepo,ixChangeset)上放置一个多列索引。在不知道列实际是什么的情况下,它们是否是独一无二的等等,很难得出更好的答案。

答案 1 :(得分:2)

问题最终是SQL Server通常选择一个绝对可怕的执行策略,基本上是反复循环遍历XML,而不是做一个理智的连接。解决方法是将XML放入临时表中,然后加入 ,这可靠地产生了良好的执行计划。