存储过程/查询根据参数中的日期运行缓慢?

时间:2018-02-13 15:55:40

标签: sql sql-server performance sql-server-2008 tsql

我有一个查询(我也为其创建了一个存储过程)。在查询中,当我使用2017年日期时(' 2017-09-30' - >' 2017-12-31')查询运行得很快(1秒)。当我将此作为带有日期参数的存储过程运行时,查询将永远运行(对于相同的数据,部分结果,大于5分钟)。

此外,当我使用2018(仅)日期时,查询和存储过程都需要更长的时间才能运行更少的数据。尽管数据存在,但我的存储过程运行了8分钟,没有加载任何行。

我不确定发生了什么。以下是一些时间

查询

Between '20170930' and '20171231' - 1 sec  - 863 rows
Between '20170930' and '20180108' - 0 sec  - 875 rows
Between '20180101' and '20180108' - 4:15 m - 12 rows

存储过程

没有真正完全加载,也许在5-8分钟之后我会得到部分结果

我的数据库中的其他商店程序不会发生这种情况。当我在查询上运行第三个日期集时,我的CPU使用率和内存是正常的。

有什么想法?谢谢!

查询:

{ Select 
M.AdultQty,
M.ChildQty, 
M.GuestQty, 
U.Usetime, 
cast(U.usetime as date) as Date, 
Right(U.usetime, 7) as 'Time', 
P.Zip as 'Zipcode'
from MUsage M
left join Usage U 
on U.usageid = M.usageid
left join pass P
on M.ScannedID = P.ID
where  p.Level = 24
and cast(U.usetime as date) between '20170930' and '20180108'
and u.code != 12
order by UseTime }

存储过程:

ALTER PROCEDURE [dbo].[SP_MEM]
(
@startdate date, 
@enddate date
)
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here

Select 
M.AdultQty,
M.ChildQty, 
M.GuestQty, 
U.Usetime, 
cast(U.usetime as date) as Date, 
Right(U.usetime, 7) as 'Time', 
P.Zip as 'Zipcode'
from MUsage M
left join Usage U 
on U.usageid = M.usageid
left join pass P
on M.ScannedID = P.ID
where  p.level = 24
and cast(U.usetime as date) between @startdate and @enddate
and u.code != 12
order by UseTime

END

更新

通过添加OPTION (RECOMPILE)商店程序适用于2017年日期范围,但不适用于2018年?

1 个答案:

答案 0 :(得分:0)

  

我有一个查询(我也为其创建了一个存储过程)。在里面   查询,当我使用2017年日期时(' 2017-09-30' - >' 2017-12-31')查询   跑得快(1秒)。当我将此作为带有日期的商店程序运行时   参数,查询需要永远运行(大于5分钟   相同的数据,部分结果)。

绝对看起来像参数嗅探的情况。请尝试以下选项。

  • 使用WITH RECOMPILE选项创建SQL Server存储过程
  • 使用SQL Server提示选项(RECOMPILE)
  • 使用SQL Server提示选项(OPTIMIZE FOR)
  • 在SQL Server存储过程上使用虚拟变量
  • 在实例级别禁用SQL Server参数嗅探
  

通过添加OPTION(RECOMPILE),商店程序适用于2017年日期   范围但不是2018年?

建议

  • 避免使用!=或<>
  

在我们使用!=运算符(或任何其他运算符)的几乎所有情况下   与NOT运算符一起,即.. NOT IN)索引查找将   不执行,而是需要表/索引扫描。

     

您可以使用><运算符尝试相同的操作。

  • 我建议将NON CLUSTERED INDEX列在usetime列上 不存在。

  • 避免在您的WHERE中使用CAST。

  

作为一般规则,对SELECT中的项目执行CAST或CONVERT   条款几乎没有成本。 (注意WHERE或中的CAST或CONVERT   ON子句可能非常昂贵,因为它们将保留SQL Server   有效利用索引)。