如何优化此查询以提高性能?

时间:2021-06-04 09:19:39

标签: sql-server stored-procedures query-optimization

这是我正在执行的查询。这个查询需要将近 10 秒才能获取 7 行的数据。所以我打算优化查询但无法得到一个想法。

ALTER PROCEDURE [dbo].[GetIBCMCaseListForBiteRegisterUserReview] --
    @projects VARCHAR(200),
    @CaseStatus INT,
    @StartDate VARCHAR(50),
    @EndDate VARCHAR(50),
    @PageNum INT,
    @PageSize INT,
    @AnimalRiskStatus INT,
    @SearchString VARCHAR(100)
AS
BEGIN
    SET FMTONLY OFF;
    SET NOCOUNT ON;

    SELECT  
        e.eventId, AD.answerCode, AD.answerText AS PatentId,
        N.UserName, B.Age, G.Gender,
        SUBSTRING(D.Dateofexposure, 4, 3) + 
            SUBSTRING(D.Dateofexposure, 1, 2) +
            SUBSTRING(D.Dateofexposure, 6, 9) AS Dateofexposure,
        L.Levelofexposure AS Typeofexposure,
        c.AnimalStatus AS AnimalStatus,
        H.DateOfVaccination, F.ALERT, I.IG, J.label,
        K.VisitCompleted, M.PepStatus, s.VisitIncomplete, 
        COUNT(1) OVER() AS totalCount,
        E.projectId AS ProjectId 
    FROM 
        IBCMEvents E
    INNER JOIN
        (SELECT 
             H.*, 
             CASE WHEN U.userId IS NULL THEN '' ELSE U.firstName + ' ' + U.lastName END AS userName
        FROM IBCMEventPushHistory H
        LEFT JOIN Users U ON H.assignedToUserId = U.userId
        WHERE H.isActiveForUser = 1
    )U ON E.eventId = U.eventId
    --INNER JOIN dbo.fnSplit(@project, ',') FN on E.projectId=FN.item

    INNER JOIN 
    (
        SELECT AD.ANSWERTEXT,IA.EVENTID,IA.answerCode 
        FROM IBCMANSWERS AS IA
        INNER JOIN IBCMAnswerDetails AD ON IA.IBCMANSWERID = AD.IBCMANSWERID AND AD.ISDELETED = 0
        INNER JOIN IBCMBusinessQuestions BQ ON AD.ibcmBusinessQuestionId = BQ.ibcmBusinessQuestionId
        WHERE IA.ibcmformid = 10 AND BQ.ibcmQuestionId = 155
    ) AS AD ON AD.EVENTID = E.EVENTID
    
    INNER JOIN 
    (
        SELECT A.eventId, MAX(B.Age) Age
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId, AD.subAnswerText AS Age
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            inner join IBCMBusinessOptions O on Q.ibcmBusinessQuestionId=O.ibcmBusinessQuestionId
            WHERE Q.ibcmQuestionId = 159 and O.ibcmOptionId=413
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId
        WHERE A.ibcmFormId = 10
        GROUP BY A.eventId
    ) B ON E.eventId = B.eventId
    LEFT JOIN 
    (
        SELECT A.eventId, MAX(B.UserName) UserName
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId,C.contactName AS UserName
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            inner join IBCMContacts C on C.contactCode=ad.answerText
            WHERE Q.ibcmQuestionId = 156 
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId  
        WHERE A.ibcmFormId = 10
        GROUP BY A.eventId
    ) N ON E.eventId = N.eventId
    INNER JOIN 
    (
        SELECT A.eventId, MAX(B.Gender) Gender
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId, AD.answerText AS Gender
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            WHERE Q.ibcmQuestionId = 157
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId
        WHERE A.ibcmFormId = 10
        GROUP BY A.eventId
    ) G ON E.eventId = G.eventId
    INNER JOIN 
    (
        SELECT A.eventId, MAX(B.Levelofexposure) Levelofexposure
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId,
            CASE WHEN o.ibcmOptionId = 418 THEN 'No exposure' ELSE
                        CASE WHEN o.ibcmOptionId = 419 THEN 'Cat 1' ELSE
                        CASE WHEN (o.ibcmOptionId = 420 OR o.ibcmOptionId = 421) Then 'Cat 2'
                        ELSE 'Cat 3' END END END  AS Levelofexposure
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            inner join IBCMBusinessOptions O on Q.ibcmBusinessQuestionId=O.ibcmBusinessQuestionId
            WHERE Q.ibcmQuestionId = 164 
            --and ad.answerText = o.optionText
            and ad.ibcmBusinessOptionId = o.ibcmBusinessOptionId 
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId
        WHERE A.ibcmFormId = 10
        GROUP BY A.eventId
    ) L ON E.eventId = L.eventId
    INNER JOIN 
    (
        SELECT A.eventId, MAX(B.Dateofexposure) Dateofexposure
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId,substring(AD.answerText, 4, 3)+substring(AD.answerText, 1, 2)+substring(AD.answerText, 6, 9)  AS Dateofexposure
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            WHERE Q.ibcmQuestionId = 160
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId
        WHERE A.ibcmFormId = 10 
        GROUP BY A.eventId
    ) D ON E.eventId = D.eventId
    INNER JOIN 
    (
        SELECT A.eventId, MAX(B.AnimalStatus) AnimalStatus
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId,CASE when O.ibcmOptionId = 461 THEN 'Alive' ELSE
            CASE WHEN O.ibcmOptionId = 462 THEN 'Dead' ELSE 'Unknown' END END AS AnimalStatus
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            inner join IBCMBusinessOptions O on Q.ibcmBusinessQuestionId=O.ibcmBusinessQuestionId
            WHERE Q.ibcmQuestionId = 173 
            and o.ibcmBusinessOptionId = ad.ibcmBusinessOptionId
            --and o.optionText = ad.answerText
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId
        WHERE A.ibcmFormId = 10
        GROUP BY A.eventId
    ) C ON E.eventId = C.eventId
    INNER JOIN 
    (
        SELECT A.eventId, MAX(B.Alert) ALERT
        FROM IBCMAnswers A
        LEFT JOIN
        (
            SELECT AD.ibcmAnswerId, 
            CASE when O.ibcmOptionId = 462 THEN 'VERY HIGH' ELSE 
            CASE WHEN (O.ibcmOptionId = 464 OR O.ibcmOptionId = 467 OR O.ibcmOptionId = 19 OR O.ibcmOptionId=20) THEN 'HIGH' ELSE 'UNKNOWN' END END AS Alert
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            inner join IBCMBusinessOptions O on Q.ibcmBusinessQuestionId=O.ibcmBusinessQuestionId
            WHERE((Q.ibcmQuestionId = 173 and O.ibcmOptionId = 462) OR (Q.ibcmQuestionId = 174 and O.ibcmOptionId = 464) OR (Q.ibcmQuestionId = 175 and O.ibcmOptionId = 467)OR(Q.ibcmQuestionId=6 AND (O.ibcmOptionId = 19 OR O.ibcmOptionId = 20))) 
            --AND AD.answerText = O.optionText
            and ad.ibcmBusinessOptionId = o.ibcmBusinessOptionId
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId 
        WHERE (A.ibcmFormId = 10 or A.ibcmFormId = 1)
        GROUP BY A.eventId
    ) F ON E.eventId = F.eventId
    OUTER APPLY(
            --103 IS THE CODE FOR FORMATING DATE IN DD/MM/YYYY FORMAT
        Select top 1 eventId,CONVERT(varchar,scheduledDate,103) as DateOfVaccination from IBCMPepScheduleDates where eventId = E.eventId AND dateCompleted is not null
    )H
    INNER JOIN 
    (
        SELECT A.eventId, MIN(B.IG) IG
        FROM IBCMAnswers A
        inner JOIN
        (
            SELECT AD.ibcmAnswerId,AD.answerText AS IG
            FROM IBCMAnswerDetails AD
            INNER JOIN IBCMBusinessQuestions Q ON AD.ibcmBusinessQuestionId = Q.ibcmBusinessQuestionId
            WHERE Q.ibcmQuestionId = 179
        ) AS B ON A.ibcmAnswerId = B.ibcmAnswerId
        WHERE A.ibcmFormId = 11
        GROUP BY A.eventId
    ) I ON E.eventId = I.eventId
    INNER JOIN 
    (
        SELECT IP.eventId,IR.label FROM IBCMPepVisitSchedule IP 
        LEFT JOIN IBCMPepRegimen IR 
        ON IP.ibcmRegimenId = IR.ibcmRegimenId
    ) J ON E.eventId = J.eventId
    INNER JOIN (
        Select eventId,Count(ibcmPepScheduleDatesId) as VisitCompleted from IBCMPepScheduleDates where dateCompleted is not null
        GROUP BY eventId
)K ON E.eventId = K.eventId
    LEFT JOIN (
        Select eventId,Count(ibcmPepScheduleDatesId) as VisitIncomplete from IBCMPepScheduleDates where dateCompleted is null
        GROUP BY eventId
)S ON E.eventId = S.eventId
OUTER APPLY (
    Select top 1 eventId ,Case when ibcmFormId = 11 Then CaseStatus End as PepStatus from IBCMAnswers
    where eventId = E.eventId 
    order by ibcmAnswerId DESC
)M
   where projectId in (select * from dbo.fnSplitBigInt (@projects)) and

  1 = CASE WHEN @StartDate != '' AND @EndDate != '' THEN CASE WHEN CAST(D.Dateofexposure AS DATE) BETWEEN CAST(@StartDate AS DATE) AND CAST(@EndDate AS Date) THEN 1 END
                ELSE CASE WHEN @StartDate != '' THEN CASE WHEN CAST(D.Dateofexposure AS DATE) >= CAST(@StartDate AS DATE) THEN 1 END
                ELSE CASE WHEN @EndDate != '' THEN CASE WHEN CAST(D.Dateofexposure AS DATE) <= CAST(@EndDate AS DATE) THEN 1 END
                ELSE 1 END END 
            END
    /*AND 1 = CASE WHEN @AnimalRiskStatus = 0 THEN 1
            WHEN @AnimalRiskStatus = 1 THEN CASE WHEN F.ALERT = 'UNKNOWN' THEN 1 END
            WHEN @AnimalRiskStatus = 2 THEN CASE WHEN F.ALERT = 'HIGH' THEN 1 END
            WHEN @AnimalRiskStatus = 3 THEN CASE WHEN F.ALERT = 'VERY HIGH' THEN 1 END
            END*/   
    AND 1 = CASE WHEN @CaseStatus = 0 THEN 1 
                --INCOMPLETE
                 when @CaseStatus = 1 Then Case when m.PepStatus =28 Then 1 END
                 when @CaseStatus = 2 Then Case when m.PepStatus = 30 Then 1 END
                 when @CaseStatus = 3 Then Case when m.PepStatus = 31 Then 1 END
                 when @CaseStatus = 4 Then Case when m.PepStatus = 33 Then 1 END
            END
    /*AND 1 = CASE WHEN @SearchString = '' THEN 1
            ELSE CASE WHEN B.Age=@SearchString OR G.Gender = @SearchString OR N.UserName like +'%'+@SearchString+'%' OR L.Levelofexposure=@SearchString 
            OR AD.answerText = @SearchString 
            OR C.AnimalStatus = @SearchString  OR
            F.ALERT = @SearchString OR I.IG =@SearchString 
            OR J.label = @SearchString 
            THEN 1
                
            ELSE 0 END 
            END*/    

    ORDER BY E.eventId DESC
    OFFSET (@PageNum - 1) * @PageSize ROWS
    FETCH NEXT @PageSize ROWS ONLY
END

以下是有关此查询的统计详细信息:

    SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 6 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 0 ms.
SQL Server parse and compile time: 
   CPU time = 3797 ms, elapsed time = 3847 ms.
Warning: Null value is eliminated by an aggregate or other SET operation.
Table 'Worktable'. Scan count 38, logical reads 152, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMAnswers'. Scan count 115, logical reads 887, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMPepScheduleDates'. Scan count 43, logical reads 98, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'Workfile'. Scan count 0, logical reads 0, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMContacts'. Scan count 7, logical reads 50183, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMAnswerDetails'. Scan count 866, logical reads 3508, physical reads 0, page server reads 0, read-ahead reads 108, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMBusinessQuestions'. Scan count 226, logical reads 2297, physical reads 0, page server reads 0, read-ahead reads 13, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMPepRegimen'. Scan count 1, logical reads 21, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMBusinessOptions'. Scan count 1, logical reads 4321, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMPepVisitSchedule'. Scan count 7, logical reads 21, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table '#B22E9BDA'. Scan count 18, logical reads 340, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMEventPushHistory'. Scan count 18, logical reads 72, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.
Table 'IBCMEvents'. Scan count 0, logical reads 54, physical reads 0, page server reads 0, read-ahead reads 0, page server read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob page server reads 0, lob read-ahead reads 0, lob page server read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 3253 ms,  elapsed time = 3367 ms.

 SQL Server Execution Times:
   CPU time = 7062 ms,  elapsed time = 7234 ms.
SQL Server parse and compile time: 
   CPU time = 0 ms, elapsed time = 0 ms.

SQL Server 执行时间: CPU 时间 = 0 毫秒,运行时间 = 0 毫秒。

完成时间:2021-06-04T14:40:39.5403064+05:30

1 个答案:

答案 0 :(得分:0)

你有这两个索引吗:

  1. X1 ON IBCContacts (contactCode) INCLUDE (contactName)
  2. IBCMAnswerDetails 上的 X2(IBCMANSWERID、ISDELETED、 ibcmBusinessQuestionId) 包括(答案)

如果不尝试创建主题...

相关问题