【问题标题】:XML-based query extremely slow through ADO.NET, instant through SSMS基于 XML 的查询通过 ADO.NET 非常慢,通过 SSMS 即时查询
【发布时间】:2012-03-27 14:36:05
【问题描述】:

我经常遇到这样的情况:一个查询通过 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 运行,实际使用的查询计划看起来很合适(索引搜索),并且在 4 毫秒内需要大约 200 次读取。运行 Web 应用程序,每秒钟大约需要 4500 次读取。

我在这里缺少什么?尽管有DBCC 调用和ARITHABORT 设置,但在通过Web 应用程序运行时是否会恢复错误的查询计划?

【问题讨论】:

  • “这是一个典型的 use-XML-to-do-a-parameterized-WHERE IN-clause hack” - 再由我运行那个?
  • BTW:“在所有这些情况下,解决方法是在 SET ARITHABORT ON 的情况下运行 ADO.NET 查询(以匹配 SSMS 使用的会话设置)或运行 DBCC DROPCLEANBUFFERS 和DBCC FREEPROCCACHE 强制查询缓存重建”——这些都不是真正的修复。那是治标不治本。
  • @MitchWheat 我稍微清理了这个解释。此查询用WHERE ixChangeset IN (...) 子句中的任意、可能大量的元素替换了一个,允许对其进行参数化并命中查询缓存。
  • @MitchWheat 是的,我知道 DBCC 之类的东西是治标不治本的,但我原本希望在 SSMS 中设置 ARITHABORT OFF 至少能给我错误的查询计划。可悲的是,情况似乎并非如此。
  • 阅读 Erland Sommarskog(SQL Server MVP)撰写的这篇文章:应用程序慢,SSMS 快? (sommarskog.se/query-plan-mysteries.html)

标签: sql-server performance ssms


【解决方案1】:

简单的解决方法是在(ixCustomer、ixRepo、ixChangeset)上放置一个多列索引。在不知道这些列实际上是什么、它们是否独特等情况下,很难找到更好的答案。

【讨论】:

  • 鉴于查询从 SSMS 运行时会立即运行,我不愿意相信这是一个索引问题。
  • @Benjamin Pollack - 当您从 SMS 运行时,它会选择一个比从代码运行时更好的索引,可能会执行一些模棱两可的字符集设置或 .NET 与默认 SMS 会话不同的操作。如果你做多列索引,它总是倾向于使用它。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    相关资源
    最近更新 更多