2010-12-02 12 views
0

Hallo Ich verwende einen SP, der 7 Minuten in einem Server dauert, der 7336 Records und 6 Sekunden in einem anderen Server hat, der 3500 Datensätze hat.SQL SP läuft langsam

Kann mir jemand helfen zu wissen, warum es passiert?

Danke, -Divya

DER SP:

SELECT WORKSHEET_ID VON PERSON PRO INNER JOIN PERSON EMPLEE ON EMPLEE.PERSON_ID = PER.PERSON_ID UND 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


die Funktion in der fünften Zeile ist derjenige, der langsam läuft. Rest des Teils in 4secs


die Funktion ausgeführt wird: BEGIN 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

Nicht ohne Details, nein. –

+1

Bitte geben Sie den Code der Stored Procedure an. –

+1

Goggle: "Parameter Sniffing" – RBarryYoung

Antwort

1

Haben die Schemata exakt übereinstimmen .. Achten Sie insbesondere auf fehlende Indizes.

+0

JA DIE SCHEMAS PASSEN GENAU. – Divya

+1

Kein Grund zu schreien. –

+0

:) von mistak caps lock war ON :) – Divya

1

Nun zu Beginn haben Sie Skalarfunktionen, die deutlich langsamer laufen, da die Anzahl der Datensätze zunimmt, da sie Zeile für Zeile agieren. Nicht nur, dass Sie die Funktionen in Joins verwendet haben, was eine schreckliche Übung ist, wenn Sie Leistung benötigen. Sie haben eine Reihe von OR-Bedingungen, die zur Langsamkeit neigen. Und obwohl es zu schwer ist, den von Ihnen geposteten Code tatsächlich zu lesen (bitte versuchen Sie, alle Groß- und Kleinbuchstaben für Schlüsselwörter zu formatieren), würde ich vermuten, dass einige dieser Bedingungen nicht sargierbar sind.

Um zu wissen, was tatsächlich passiert, überprüfen Sie den Ausführungsplan (SQL Server) oder Explain Plan (mySQL und andere, denke ich) oder die entsprechende Funktion in Ihrer Datenbank. Vermutlich werden Sie Tabellenscans finden, die natürlich mit zunehmender Anzahl der Datensätze deutlich langsamer werden.

Möglicherweise haben Sie auch ein Problem mit dem Parameter Sniffing. Bitte googlen Sie, um zu sehen, wie Sie das beheben können.

0

Eine Verbesserung wäre, sicherzustellen, dass dbo.FN_GETRPTSSIGNMENTID nur einmal ausgeführt wird.

Derzeit wird es dreimal ausgeführt.
Sie können zwei dieser Anrufe durch Verbinden mit dem Feld des (einen) verbleibenden Anrufs ersetzen.

So etwas wie

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 [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