【问题标题】:stored procedure is execution taking long time in sql server存储过程在 sql server 中执行需要很长时间
【发布时间】:2014-05-12 19:47:03
【问题描述】:

我有一个名为 Transaction_tbl 的表,其中包含超过 400 000 条记录。这是表结构:

CREATE TABLE [dbo].[Transaction_tbl](
    [transactID] [numeric](18, 0) IDENTITY(1,1) NOT NULL,
    [TBarcode] [varchar](20) NULL,
    [cmpid] [int] NULL,
    [Locid] [int] NULL,
    [PSID] [int] NULL,
    [PCID] [int] NULL,
    [PCdID] [int] NULL,
    [PlateNo] [varchar](20) NULL,
    [vtid] [int] NULL,
    [Compl] [bit] NULL,
    [self] [bit] NULL,
    [LstTic] [bit] NULL,
    [Gticket] [int] NULL,
    [Cticket] [int] NULL,
    [Ecode] [varchar](50) NULL,
    [dtime] [datetime] NULL,
    [LICID] [int] NULL,
    [PAICID] [int] NULL,
    [Plot] [varchar](50) NULL,
    [mkid] [int] NULL,
    [mdlid] [int] NULL,
    [Colid] [int] NULL,
    [Comments] [varchar](100) NULL,
    [Kticket] [int] NULL,
    [PAmount] [numeric](18, 2) NULL,
    [Payid] [int] NULL,
    [Paid] [bit] NULL,
    [Paydate] [datetime] NULL,
    [POICID] [int] NULL,
    [DelDate] [datetime] NULL,
    [DelEcode] [nvarchar](50) NULL,
    [PAICdate] [datetime] NULL,
    [KeyRoomDate] [datetime] NULL,
    [Status] [int] NULL,
 CONSTRAINT [PK_Transaction_tbl] PRIMARY KEY CLUSTERED 
(
    [transactID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

我在 Locid, dtime 列上有一个非聚集索引。 我有一个这样的存储过程:

ALTER procedure [dbo].[IBS_fetchreleasedinpodiumgridnew]
   @locid INTEGER = NULL
AS BEGIN
   SET NOCOUNT ON
  DECLARE @TodayMinus7Days DATETIME
Declare @krrt integer
Declare @DT integer
   SET @TodayMinus7Days = getdate()-1



SELECT  
       t.TBarcode, t.PlateNo, t.DelEcode,cast(t.Paydate as Time) [REQ],
       datediff(MINUTE, t.PayDate,
             CASE t.Status
                WHEN 3 THEN GETDATE()
                WHEN 4 THEN t.KeyRoomDate
                When 5 THEN  t.KeyRoomDate
                End) as KRRT,

             datediff(MINUTE,t.PayDate,
             CASE t.Status
              WHEN 3 THEN GETDATE()
              WHEN 4 THEN GETDATE()
             WHEN 5 THEN t.DelDate
             END) as DT

   FROM    
       dbo.Transaction_tbl t

   WHERE   

   ( 
       ([status] IN (3,4))
       OR 
       ([status] = 5 AND DATEDIFF(n, DelDate, GETDATE()) <= 3)
   )
   AND locid = 6 AND dtime >= @TodayMinus7Days
   ORDER BY  
       paydate 
       end

我的执行计划是这样的:

但大多数情况下这需要很长时间才能执行..在这种情况下,我如何提高我的存储过程执行性能?
我想使用的任何其他方法..任何帮助都非常有用。谢谢

查询执行计划显示排序需要很长时间..所以如果我在paydate 上给出索引,我的查询性能会提高吗? 而不是这个dtime &gt;= @TodayMinus7Days,我给出了这样的代码:

dtime >= OPTION (optimize for (@TodayMinus7Days))

但出现错误:关键字“OPTION”附近的语法不正确。

【问题讨论】:

  • 从查询计划中可以看出,排序耗时最长。
  • 对我来说; ORDER BY paydate 是这里的罪魁祸首。尝试在 paydate (OR) 上创建索引,按顺序使用索引列
  • 有什么你没有给我们看的吗?这个计划建议了一个不应该存在的内部连接。
  • 1) “超过 4 条缺少记录”是什么意思。 2)当它“慢”时,你大约返回了多少行。 3)有多慢?例如,2 秒。 20 分钟等 4) 为什么@TodayMinus7Days = getdate()-1。 5) 你试过 WITH (INDEX (Your_Locid_dtime_Index)) 6) 你试过类似“option (optimize for (@TodayMinus7Days = '2000-01-01'))”的提示吗
  • 一段时间后,我想我可以猜到您的选择可能正在使用您的 Locid_dtime 索引——尽管查询计划图片并没有明确显示这一点——如果你只有 PK 和您提到的 1 个索引,它正在使用我在提示中建议的索引。

标签: sql-server sql-server-2008 stored-procedures sql-server-performance


【解决方案1】:

除了优化查询之外,我还可以立即提出一些建议来提高存储过程的性能。

参数嗅探:当存储过程传递一个参数时,它会分析数据集以找出最有效的索引。这很有用,尽管计划被缓存,并且会过时,导致存储的过程在低效的执行计划上运行。

解决方案:重新声明参数或针对未知参数值优化存储过程

抑制行数:提高存储过程性能的最简单的事情之一就是设置 NOCOUNT ON。这将阻止 SQL Server 在执行每个语句后将消息发送回客户端,而存储过程不需要这样做。这似乎是一个小的改进,但结果是显而易见的。

解决方案:设置 NOCOUNT ON

下面的 sn-p 有一个示例,说明它们在您的存储过程中的位置。请注意,如果您重新声明参数,则无需针对未知进行优化,反之亦然。

CREATE PROCEDURE dbo.example_proc   
(   
    @USER_PARAM VARCHAR(200)
)
AS
BEGIN

    -- suppress  the number of rows returned
    SET NOCOUNT ON;

    -- Re-declaring the variable will prevent paramater sniffing
    DECLARE @LOCAL_USER_PARAM VARCHAR(200) = @USER_PARAM

    SELECT
        *
    FROM some_table st
    WHERE st.some_column = @LOCAL_USER_PARAM

    -- If you don't re-declare params, you can add this line
    OPTION (OPTIMIZE FOR (@USER_PARAM UNKNOWN))
    --

END 
GO

【讨论】:

  • 你的意思是重新声明参数或优化未知参数值的存储过程
  • 我给出了这样的 dtime >= OPTION (优化 (@TodayMinus7Days))..但出现错误
  • 您在查询中正常使用参数,然后在底部添加行 OPTION (OPTIMIZE FOR (@TodayMinus7Days UNKNOWN))
  • 为什么指定 UNKNOWN
  • SQL server 将使用针对特定值进行优化的执行计划等来编译存储过程。通过告诉它针对未知进行优化,这告诉它不要使用可能已过时并针对不同值进行优化的预先准备好的执行计划。
【解决方案2】:

尝试使用“with recompile”根据参数得到更合适的执行计划。就我而言,它有助于将时间从大约 1 小时减少到几分钟。希望它也适用于您的情况。

exec [dbo].[IBS_fetchreleasedinpodiumgridnew] 1 with recompile

【讨论】:

    【解决方案3】:

    检查方式手动运行 SP。如果它工作正常而不是您的问题是隔离级别。 在存储过程的开头添加这些行。

    SET NOCOUNT ON; 
    SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  ;
    

    【讨论】:

      猜你喜欢
      • 2021-09-19
      • 1970-01-01
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 2014-03-09
      相关资源
      最近更新 更多