【问题标题】:SQL SP runs SlowSQL SP 运行缓慢
【发布时间】:2010-12-02 02:28:50
【问题描述】:

嗨 我在有 7336 个记录的服务器中使用一个需要 7 分钟的 SP 在另一台拥有 3500 条记录的服务器上运行 6 秒。

谁能帮我知道为什么会这样?

谢谢, -Divya

SP:

选择工作表_ID 来自个人 内联人 EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID 和 dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, @p_SEC_ACCOUNT_ID) > 0

  LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN 
  ON PERSON_ASGN.ASSIGNMENT_ID =    
                  dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)

 LEFT JOIN LOOKUP EMPLEE_ASGN_STAT
 ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE'
 AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
 INNER JOIN 
(SELECT w1.ASSIGNMENT_ID, w1.WORKSHEET_ID, w1.EFFECTIVE_DATE, w1.APPROVED_BY, w3.CREATED_BY
    FROM WORKSHEET_PAYROLL_VW w1 
    INNER JOIN WORKSHEET w3 
    ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
    WHERE w1.EFFECTIVE_DATE = CASE 
                             WHEN @p_MOST_RECENT_ONLY = 'Y' 
                             THEN (SELECT MAX(w2.EFFECTIVE_DATE)
                                   FROM WORKSHEET_PAYROLL_VW w2
                                   WHERE w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID 
                                   AND (ISNULL(@p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) =w2.EFFECTIVE_DATE)) 
                             ELSE ISNULL(@p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
                             END

       )
 PERSON_WKS
 ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
 INNER JOIN  
  (SELECT ASSIGNMENT_ID, VALUE
   FROM ASSIGNMENT_HISTORY AH
   WHERE    FIELD_NAME ='HOME PAYROLL GROUP' 
   AND EFFECTIVE_DATE =  (SELECT MAX(EFFECTIVE_DATE)
                          FROM ASSIGNMENT_HISTORY 
                          WHERE ASSIGNMENT_ID = AH.ASSIGNMENT_ID 
                          AND   EFFECTIVE_DATE <=getDate() 
                          AND   FIELD_NAME = 'HOME PAYROLL GROUP')

    )HOME_PAYROLL 
    ON HOME_PAYROLL.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)

   WHERE 
    (@p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = @p_PERSON_ID)
     AND
    (@p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,1,1)
     OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,2,1))
     AND
    (@p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = @p_POLICY_ID)
     AND
    (@p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=@p_HOME_COUNTRY_ID) 
     AND
    (@p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=@p_HOME_CITY_ID )
     AND
    (@p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=@p_HOME_COMPANY_ID ) 
    AND
    (@p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=@p_HOME_DIVISION_ID )
     AND
    (@p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=@p_HOST_COUNTRY_ID )
     AND
    (@p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=@p_HOST_CITY_ID )
     AND
    (@p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=@p_HOST_COMPANY_ID )
     AND
    (@p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=@p_HOST_DIVISION_ID )
     AND
    (@p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=@p_CREATED_BY )
     AND
    (@p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=@p_APPROVED_BY )
     AND
    (@p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=@p_payroll_code )

按 PER.LAST_NAME ASC 排序, PER.FIRST_NAME ASC, PERSON_WKS.EFFECTIVE_DATE DESC


第 5 行中的函数是运行缓慢的函数。其余部分在 4 秒内运行


功能: 开始 宣布 @v_ASGN_COUNT 整数, @v_RESULT INT

SELECT @v_ASGN_COUNT = COUNT(ASSIGNMENT_ID) --to find out if this employee has any assignment
FROM ASSIGNMENT
WHERE EXPATRIATE_PERSON_ID = @p_PERSON_ID AND
      ASGN_STAT_CODE IN ('PD','A','I')

IF(@v_ASGN_COUNT > 0)   --yes assignment, check against SECURITY_ASSIGNMENT_VW
BEGIN
    SELECT @v_RESULT = COUNT(ASSIGNMENT_ID)
    FROM SECURITY_ASSIGNMENT_VW
    WHERE SEC_ACCOUNT_ID = @p_SEC_ACCOUNT_ID AND
          ASSIGNMENT_ID IN (SELECT ASSIGNMENT_ID
                FROM ASSIGNMENT
                WHERE EXPATRIATE_PERSON_ID = @p_PERSON_ID AND
                      ASGN_STAT_CODE IN ('PD','A','I'))
END
ELSE    --no assignment, so check against SECURITY_PERSON_VW
BEGIN
    SELECT @v_RESULT = COUNT(PERSON_ID)
    FROM SECURITY_PERSON_VW 
    WHERE SEC_ACCOUNT_ID = @p_SEC_ACCOUNT_ID AND
          PERSON_ID = @p_PERSON_ID
END

RETURN @v_RESULT

结束

【问题讨论】:

  • 不是没有细节,没有。
  • 请提供存储过程的代码。

标签: sql


【解决方案1】:

模式是否完全匹配...特别是检查缺失的索引。

【讨论】:

  • 是的,模式完全匹配。
  • :) misak caps lock 已开启 :)
【解决方案2】:

首先你有标量函数,随着记录数量的增加,它们的运行速度会明显变慢,因为它们逐行处理。不仅您在连接中使用了函数,如果您需要性能,这是一种可怕的做法。你有一堆 OR 条件往往会变慢。虽然实际阅读您发布的代码太难了(请尝试格式化并且只对关键字使用全部大写),但我怀疑其中一些条件是不可预测的。

要了解实际发生的情况,请查看执行计划 (SQL Server) 或解释计划(我认为是 mySQL 和其他)或数据库中的等效功能。您可能会发现随着记录数量的增加,表扫描当然会变得非常慢。

您可能还遇到了参数嗅探的问题。请谷歌看看如何解决这个问题。

【讨论】:

    【解决方案3】:

    一项改进是确保dbo.FN_GETRPTSSIGNMENTID 只执行一次。

    目前,它被执行了 3 次。
    您可以通过加入(一个)剩余呼叫的字段来替换其中两个呼叫。

    类似

    SELECT  WORKSHEET_ID 
    FROM    PERSON PER
            INNER JOIN PERSON EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID AND dbo.FN_CHECKRPTSECURITY(EMPLEE.PERSON_ID, @p_SEC_ACCOUNT_ID) > 0
            INNER JOIN (
              SELECT  w1.ASSIGNMENT_ID
                      , w1.WORKSHEET_ID
                      , w1.EFFECTIVE_DATE
                      , w1.APPROVED_BY
                      , w3.CREATED_BY
              FROM    WORKSHEET_PAYROLL_VW w1 
                      INNER JOIN WORKSHEET w3 ON w3.WORKSHEET_ID = w1.WORKSHEET_ID
              WHERE   w1.EFFECTIVE_DATE = 
                        CASE  WHEN @p_MOST_RECENT_ONLY = 'Y' 
                        THEN  (
                                SELECT  MAX(w2.EFFECTIVE_DATE)
                                FROM    WORKSHEET_PAYROLL_VW w2
                                WHERE   w1.ASSIGNMENT_ID = w2.ASSIGNMENT_ID AND (ISNULL(@p_WKS_EFFECTIVE_DATE,w2.EFFECTIVE_DATE) = w2.EFFECTIVE_DATE)
                              ) 
                        ELSE ISNULL(@p_WKS_EFFECTIVE_DATE,w1.EFFECTIVE_DATE)
                        END
    
            ) PERSON_WKS ON PERSON_WKS.ASSIGNMENT_ID = dbo.FN_GETRPTASSIGNMENTID(EMPLEE.PERSON_ID)
            INNER JOIN  (
              SELECT  ASSIGNMENT_ID
                      , VALUE 
              FROM    ASSIGNMENT_HISTORY AH
              WHERE   FIELD_NAME ='HOME PAYROLL GROUP' 
                      AND EFFECTIVE_DATE = (
                                              SELECT  MAX(EFFECTIVE_DATE) 
                                              FROM    ASSIGNMENT_HISTORY   
                                              WHERE   ASSIGNMENT_ID = AH.ASSIGNMENT_ID 
                                                      AND EFFECTIVE_DATE <=getDate() 
                                                      AND  FIELD_NAME = 'HOME PAYROLL GROUP'
                                          )                   
            LEFT JOIN SEARCH_ASSIGNMENT_VW PERSON_ASGN ON PERSON_ASGN.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
            LEFT JOIN LOOKUP EMPLEE_ASGN_STAT ON EMPLEE_ASGN_STAT.TYPE_ = 'ASSIGNMMENT_STATUS_CODE' AND EMPLEE_ASGN_STAT.CODE = PERSON_ASGN.ASGN_STAT_CODE
           ) HOME_PAYROLL ON HOME_PAYROLL.ASSIGNMENT_ID = PERSON_WKS.ASSIGNMENT_ID
     WHERE  (@p_SELECTED_PERSON_ONLY = 'N' OR EMPLEE.PERSON_ID = @p_PERSON_ID) 
            AND (@p_ASGN_STAT_CODE IS NULL OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,1,1) OR PERSON_ASGN.ASGN_STAT_CODE = SUBSTRING(@p_ASGN_STAT_CODE,2,1)) 
            AND (@p_POLICY_ID IS NULL OR PERSON_ASGN.PROGRAM_CODE = @p_POLICY_ID) 
            AND (@p_HOME_COUNTRY_ID IS NULL OR PERSON_ASGN.HOMECOUNTRYID=@p_HOME_COUNTRY_ID) 
            AND (@p_HOME_CITY_ID IS NULL OR PERSON_ASGN.HOMECITYID=@p_HOME_CITY_ID ) 
            AND (@p_HOME_COMPANY_ID IS NULL OR PERSON_ASGN.HOMEBUSINESSID=@p_HOME_COMPANY_ID ) 
            AND (@p_HOME_DIVISION_ID IS NULL OR PERSON_ASGN.HOMECOMPONENTID=@p_HOME_DIVISION_ID ) 
            AND (@p_HOST_COUNTRY_ID IS NULL OR PERSON_ASGN.HOSTCOUNTRYID=@p_HOST_COUNTRY_ID ) 
            AND (@p_HOST_CITY_ID IS NULL OR PERSON_ASGN.HOSTCITYID=@p_HOST_CITY_ID ) 
            AND (@p_HOST_COMPANY_ID IS NULL OR PERSON_ASGN.HOSTBUSINESSID=@p_HOST_COMPANY_ID ) 
            AND (@p_HOST_DIVISION_ID IS NULL OR PERSON_ASGN.HOSTCOMPONENTID=@p_HOST_DIVISION_ID ) 
            AND (@p_CREATED_BY IS NULL OR PERSON_WKS.CREATED_BY=@p_CREATED_BY ) 
            AND (@p_APPROVED_BY IS NULL OR PERSON_WKS.APPROVED_BY=@p_APPROVED_BY ) 
            AND (@p_payroll_code IS NULL OR HOME_PAYROLL.VALUE=@p_payroll_code )
    ORDER BY 
            PER.LAST_NAME ASC
            , PER.FIRST_NAME ASC
            , PERSON_WKS.EFFECTIVE_DATE DESC
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-29
      • 2017-09-24
      • 2011-09-01
      • 2023-04-01
      • 1970-01-01
      • 2011-10-08
      • 1970-01-01
      相关资源
      最近更新 更多