SQL 查询和存储过程执行后的读取次数显着不同

Posted

技术标签:

【中文标题】SQL 查询和存储过程执行后的读取次数显着不同【英文标题】:TSQL Number of reads significantly different after query and stored procedure execution 【发布时间】:2012-10-22 11:18:54 【问题描述】:

在查询优化之后,我得到的结果是好的,我想改变存储过程,但是在 SP 执行之后得到的结果比查询执行之后更糟糕!

首先,我认为阅读次数。结果如此不同的原因是什么?

查询与SP中的相同,唯一的区别是在查询中我声明了参数,但在SP中是输入参数。设置为参数的值也相同。为了避免“记录数据”,我首先重新编译了 SP,然后进行了 DROP 和 CREATE,但结果也大不相同。

查询是这样的(表名和列名因为简化而改变,列数减少):

DECLARE @Var1 varchar(20)    
SET @Var1 = @Var1 + '%'       

DECLARE @Var2 TIMESTAMP    
SELECT @Var2 = CONVERT(TIMESTAMP, ID, 0)    
FROM    
 X_TIMESTAMPS (NOLOCK)    
WHERE    
 TABLE = 'T1'     


declare @Var3 varbinary(8)    
SELECT @Var3 = max(IdTimeStamps)    
FROM    
 T1 (NOLOCK)     

SELECT o.c1  
  , o.c2   
  , o.c3    
  , v.c4    
  , v.c5   
  , p.c6    
  , p.c7    
  , va.c8    
  , isnull(s.c9, '') AS c9    
  , CASE o.c10    
     WHEN 1 THEN    
      0    
     ELSE    
      1    
    END c10   
  , o.c11    
FROM    
 T1 o (NOLOCK)    
 JOIN T2 p (NOLOCK)    
  ON o.c1 = p.c12    
 JOIN T3 i (NOLOCK)    
  ON (o.c13 = i.c14)    
 JOIN T4 v (NOLOCK)    
  ON (v.c4 = i.c15)    
 LEFT JOIN T5 s (NOLOCK)    
  ON (o.c16 = s.c17)    
 JOIN T6 va (NOLOCK)    
  ON o.c11 = va.c18    
WHERE    
 o.c1 LIKE @Var1    
 AND o.c2 > @Var2 

程序是这样的:

CREATE PROCEDURE [dbo].[SP1] @Var1 varchar(20) ='' 
WITH RECOMPILE  
AS        
BEGIN

    PREVIOUS QUERY WITHOUT DECLARATION FOR @Var1

END

提前TnX!

内曼加

【问题讨论】:

我们需要更多信息。 sp的代码是什么,命中了什么表,你做了什么优化,优化前的执行计划是什么,优化后是什么? 我编辑了问题并添加了查询和 SP。 【参考方案1】:

这是因为不同的执行计划用于带常量的查询和带参数的sp。你可以尝试一些技巧

创建内联表函数并尝试一下

create function sf_test
(
    @param1 int
)
returns table
as
return
    your query using @in_param1

像这样在你的过程中声明额外的参数

create procedure sp_test
(
    @param1 int
)
as
begin
    declare @in_param1 int

    select @in_param1 = @param1

    your query using @in_param1
end

您也可以尝试在您的过程中使用选项with recompile,或使用动态SQL

【讨论】:

就是这样!我添加了虚拟参数并正常继续执行。 @SpectralGhost 在另一个答案中添加的文章也非常有用,并详细解释了参数嗅探问题。 WITH RECOMPILE 之前尝试过,但在这种情况下没有用。【参考方案2】:

这几乎肯定是parameter sniffing 问题。就个人而言,我喜欢使用虚拟变量选项来解决此问题,并且(仅当我遇到此问题时)创建设置为传入参数值的变量。

【讨论】:

那是参数嗅探问题!通过添加虚拟参数来解决。 TnX!

以上是关于SQL 查询和存储过程执行后的读取次数显着不同的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server - 减少读取次数[关闭]

Asp.net(C#) 获取 执行sql server 语句/存储过程后的 多个返回值?

存储过程执行时间过长时发出 SQL 警报

oracle存储过程中if条件后的sql没有执行

Mysql将存储过程执行后的值赋值给变量

VB调用SQL存储过程异步执行问题