【问题标题】:Same query has different execution plan in SP同一查询在 SP 中具有不同的执行计划
【发布时间】:2015-01-24 17:46:24
【问题描述】:

当完全相同的查询放在存储过程中时,它会生成一个完全不同的执行计划,大约需要 18 秒。

与我单独运行时(并且只是在查询上方声明变量)相比,它的运行速度要快得多~ 1-2 秒。

我该怎么做才能使 SP 中的查询在单独运行时使用执行计划运行?仅供参考,我什至通过创建一个全新的存储过程并将查询复制粘贴到其中来重现该问题。大约 18 秒的相同结果。

查询如下图供参考

select
    COUNT(b.BookKey) as RowCounter
from
    Books b (nolock) 
    inner join BookPublishRegions bp (nolock)
      on b.BookKey = bp.BookKey               
where           
    b.IsUnavailable = 0 and 
    (@AuthorKey is null or b.AuthorKey = @AuthorKey) and
    (b.Price between @MinPrice and @MaxPrice) and
    contains(bp.PublishRegionName, @SearchTerm)

我有关于 b.IsUnavailable、b.AuthorKey、b.Price 的索引和关于 bp.PublishRegionName 的全文索引。

有什么想法吗?

【问题讨论】:

  • 参数嗅探可能是一个原因。这可能对你有帮助stackoverflow.com/questions/27194253/…
  • 感谢@GiorgosBetsos。我尝试了将 SearchTerm 声明为局部变量并设置为参数值的解决方案(根据该帖子中推荐的解决方案),但它仍然没有成功。还有什么想法吗?
  • 更正上述评论。我为 AuthorKey 设置了另一个局部变量,现在它又快速运行了……这是否意味着我必须为存储过程中使用的所有参数设置新的局部变量??
  • 要禁用参数嗅探,您需要为 where 子句中使用的每个输入变量声明一个局部变量
  • 您可以通过为导致问题的参数添加 OPTION (OPTIMIZE FOR UNKNOWN) 来避免所有的局部变量废话。另见thisthis

标签: sql asp.net .net sql-server performance


【解决方案1】:

即使查询看起来相同,局部变量和参数也是完全不同的东西。使用局部变量,SQL Server 根据统计平均密度值估计行数,因为实际值在编译时是未知的。但是,在参数的情况下,实际参数值被“嗅探”,并且从提供的实际值的统计直方图中收集估计值。如果估计的行数差异很大,则生成的执行计划可能会有所不同。

您提到的症状可能表明统计数据已过时或提到的参数嗅探问题。尝试使用 FULLSCAN 更新表上的统计信息并重新运行参数化查询以查看计划是否更好:

UPDATE STATISTICS ON dbo.Books WITH FULLSCAN;
UPDATE STATISTICS ON dbo.BookPublishRegions WITH FULLSCAN;

【讨论】:

  • 谢谢@DanGuzman。我运行了这两个语句,不幸的是执行时间没有改善。
  • @Ricky,您可以尝试DBCC FREEPROCCACHE 以确保您获得新计划。如果时间仍然很糟糕,则排除了嗅探问题。
猜你喜欢
  • 2015-12-10
  • 2011-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2012-11-09
相关资源
最近更新 更多