2010-12-02 3 views
0

Привет Я использую SP, который занимает 7 минут на сервере, который имеет 7336 recrds и 6 секунд на другом сервере, который имеет 3500 записей.SQL SP работает Slow

Может кто-нибудь помочь мне узнать, почему это происходит?

Благодаря, -Divya

СП:

ВЫБОР WORKSHEET_ID ОТ человека в INNER JOIN PERSON EMPLEE ПО 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 [email protected]_HOME_COUNTRY_ID) 
    AND 
    (@p_HOME_CITY_ID IS NULL OR [email protected]_HOME_CITY_ID) 
    AND 
    (@p_HOME_COMPANY_ID IS NULL OR [email protected]_HOME_COMPANY_ID) 
    AND 
    (@p_HOME_DIVISION_ID IS NULL OR [email protected]_HOME_DIVISION_ID) 
    AND 
    (@p_HOST_COUNTRY_ID IS NULL OR [email protected]_HOST_COUNTRY_ID) 
    AND 
    (@p_HOST_CITY_ID IS NULL OR [email protected]_HOST_CITY_ID) 
    AND 
    (@p_HOST_COMPANY_ID IS NULL OR [email protected]_HOST_COMPANY_ID) 
    AND 
    (@p_HOST_DIVISION_ID IS NULL OR [email protected]_HOST_DIVISION_ID) 
    AND 
    (@p_CREATED_BY IS NULL OR [email protected]_CREATED_BY) 
    AND 
    (@p_APPROVED_BY IS NULL OR [email protected]_APPROVED_BY) 
    AND 
    (@p_payroll_code IS NULL OR [email protected]_payroll_code) 

ORDER BY PER.LAST_NAME ASC,PER.FIRST_NAME ASC, PERSON_WKS.EFFECTIVE_DATE DESC


Функция в 5-й линии является тот, который работает медленно. Остальная часть работает в 4secs


Функция: НАЧАТЬ DECLARE @v_ASGN_COUNT INT, @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 

END

+4

Не без подробностей, нет. – 2010-12-02 02:31:17

+1

Просьба указать код хранимой процедуры. – 2010-12-02 02:31:18

ответ

1

Имеют ли схемы точно соответствовать .. в частности, проверить отсутствие индексов.

1

Начну с того, что у вас есть скалярные функции, которые будут работать значительно медленнее по мере увеличения количества записей, потому что они обрабатывают ряд за агонизацией-строку. Мало того, что вы использовали функции в объединениях, что является ужасной практикой, если вам нужна производительность. У вас есть множество условий ИЛИ, которые имеют тенденцию к медлительности. И хотя слишком сложно действительно прочитать код, который вы опубликовали (пожалуйста, попробуйте отформатировать и использовать только кепки для ключевых слов), я бы заподозрил, что некоторые из этих условий не поддаются сопоставлению.

Чтобы узнать, что на самом деле происходит, проверьте план выполнения (SQL Server) или объясните план (mySQL и другие, я думаю) или эквивалентную функцию в вашей базе данных. Вероятно, вы найдете сканирование таблицы, которая, конечно же, будет значительно медленнее, так как количество записей увеличивается.

У вас может также возникнуть проблема с параметром sniffing. Пожалуйста, google, чтобы узнать, как это исправить.

0

Одним из усовершенствований было бы удостовериться, что dbo.FN_GETRPTSSIGNMENTID только выполняется один раз.

В настоящее время он выполняется три раза.
Вы можете заменить два этих вызова, присоединившись к полю (одного) вызова для повторного вызова.

Что-то вроде

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 [email protected]_HOME_COUNTRY_ID) 
     AND (@p_HOME_CITY_ID IS NULL OR [email protected]_HOME_CITY_ID) 
     AND (@p_HOME_COMPANY_ID IS NULL OR [email protected]_HOME_COMPANY_ID) 
     AND (@p_HOME_DIVISION_ID IS NULL OR P[email protected]_HOME_DIVISION_ID) 
     AND (@p_HOST_COUNTRY_ID IS NULL OR [email protected]_HOST_COUNTRY_ID) 
     AND (@p_HOST_CITY_ID IS NULL OR [email protected]_HOST_CITY_ID) 
     AND (@p_HOST_COMPANY_ID IS NULL OR [email protected]_HOST_COMPANY_ID) 
     AND (@p_HOST_DIVISION_ID IS NULL OR [email protected]_HOST_DIVISION_ID) 
     AND (@p_CREATED_BY IS NULL OR [email protected]_CREATED_BY) 
     AND (@p_APPROVED_BY IS NULL OR [email protected]_APPROVED_BY) 
     AND (@p_payroll_code IS NULL OR [email protected]_payroll_code) 
ORDER BY 
     PER.LAST_NAME ASC 
     , PER.FIRST_NAME ASC 
     , PERSON_WKS.EFFECTIVE_DATE DESC