簡體   English   中英

為什么此SQL Server查詢這么慢?

[英]Why is this SQL Server query so slow?

該查詢需要4秒鍾才能運行,它返回大約62000行。 @ c,@ p和@a是由整數組成的字符串,根據需要過濾的內容,以逗號分隔或為空。不幸的是,這不能更改。

我試圖在不使用過濾器的情況下運行此程序,但這沒有任何區別。 我對SQL相當陌生。

這里有3個常用的表表達式,可以減少多余的代碼行。

我希望能夠在不到一秒鍾的時間內運行

DECLARE @UId int = '817',
        @c varchar(max) = '',
        @p varchar(max) = '',
        @a varchar(max) = ''

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF OBJECT_ID('tempdb..#FilteredData') IS NOT NULL 
     DROP TABLE #FilteredData;

WITH cteuag AS 
(
    SELECT
        uag.CId,
        uag.AuthorIsatIonGroupId,
        rn = ROW_NUMBER() OVER (PARTITION BY uag.[UId], uag.CId, uag.AuthorIsatIonGroupId ORDER BY uag.CId)
    FROM 
        uag
    WHERE 
        uag.[UId] = @UId
        AND uag.IsDeleted = 0
        AND (@c = '' OR (@c LIKE CONVERT(varchar(4), uag.CId)
                         OR @c LIKE '%,' + CONVERT(varchar(4), uag.CId) + ',%'
                         OR @c LIKE CONVERT(varchar(4), uag.CId) + ',%'
                         OR @c LIKE '%,' + CONVERT(varchar(4), uag.CId))
            )
),
cteuc AS
(
    SELECT
        uc.CId,
        cteuag.AuthorIsatIonGroupId,
        uc.[UId],
        i.FirstName + Iif(i.MiddleName IS NOT NULL, ' ' + i.MiddleName + ' ', ' ') + i.Surname AS [AName],
        rn = ROW_NUMBER() OVER (PARTITION BY uc.CId, uc.[UId] ORDER BY uc.ModifiedAt)
    FROM 
        uc
    INNER JOIN 
        cteuag ON cteuag.CId = uc.CId
               AND uc.IsDeleted = 0
               AND (@a = '' OR (@a LIKE CONVERT(varchar(4), uc.[UId])
                                OR @a LIKE '%,' + CONVERT(varchar(4), uc.[UId]) + ',%'
                                OR @a LIKE CONVERT(varchar(4), uc.[UId]) + ',%'
                                OR @a LIKE '%,' + CONVERT(varchar(4), uc.[UId]))
                   )
    INNER JOIN 
        ui ON ui.[UId] = uc.[UId]
           AND ui.IsDeleted = 0
    INNER JOIN 
        i ON i.PId = ui.IndividualId
),
ctel AS
(
    SELECT
        la.LId,
        p.CId,
        la.[UId],
        rn = ROW_NUMBER() OVER (PARTITION BY la.LId ORDER BY la.DateUpdated DESC)
    FROM  
        la 
    INNER JOIN 
        p ON p.Id = la.PId
          AND p.IsDeleted = 0
          AND la.IsDeleted = 0
          AND la.[UId] IS NOT NULL
    INNER JOIN 
        l ON la.LId = l.Id
          AND l.IsDeleted = 0
)
SELECT
    c.Id AS CId,
    c.[Name] AS CName,
    u.Id AS AId,
    cteuc.AName AS AName,
    ctel.LId AS LId,
    qh.Id AS QhId,
    q.Id AS QId,
    q.IsTrue AS isTrue,
    p.Id AS PId,
    p.[Name] AS PName,
    qi.FinalCalculation AS Calculation
INTO 
    #FilteredData
FROM 
    c
INNER JOIN 
    cteuc ON cteuc.CId = c.Id
          AND cteuc.Rn = 1
          AND c.IsDeleted = 0
LEFT OUTER JOIN 
    u ON u.Id = Iif(cteuc.AuthorIsatIonGroupId = 1, @UId, cteuc.[UId])
      AND u.IsDeleted = 0
LEFT OUTER JOIN 
    ctel ON ctel.CId = c.Id
         AND ctel.Rn = 1
         AND ctel.[UId] = u.Id
LEFT OUTER JOIN 
    (la
        INNER JOIN 
            qla ON qla.LeadActivityId = la.Id
                AND la.IsDeleted = 0
                AND la.ActivityTypeId = 4
        INNER JOIN 
            qh ON qla.QhId = qh.Id
               AND qh.IsDeleted = 0
               AND qh.IsReRated = 0
        LEFT OUTER JOIN 
            (q 
             INNER JOIN 
                 p ON p.Id = q.PId
                   AND q.IsDeleted = 0
                   AND p.IsDeleted = 0
        ) ON q.QhId = qh.Id) ON la.[UId] = u.Id
        AND la.LId = ctel.LId
        AND 
        (
            @p = ''
            OR 
            (
                @p LIKE CONVERT(varchar(4), p.Id)
                OR @p LIKE '%,' + CONVERT(varchar(4), p.Id) + ',%'
                OR @p LIKE CONVERT(varchar(4), p.Id) + ',%'
                OR @p LIKE '%,' + CONVERT(varchar(4), p.Id)
            )
        )
    LEFT OUTER JOIN 
    (
        SELECT
            qi1.QId,
            SUM(Iif(qi1.Calculation = 0, 0, qi1.Calculation + qi1.Extra)) AS FinalCalculation
        FROM qi
        WHERE qi1.IsDeleted = 0
        GROUP BY QId
    ) AS qi ON qi.QId = q.Id
WHERE 
    (
        @p = ''
        OR 
        (
            p.Id IS NOT NULL
            OR qh.Id IS NULL
        )
    )

SELECT * FROM #FilteredData

編輯

只需清楚一點,以上查詢的運行速度不會比此查詢慢:

DECLARE @UId int = '817'

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

IF OBJECT_ID('tempdb..#FilteredData') IS NOT NULL DROP TABLE #FilteredData;

WITH cteuag AS 
(
    SELECT
        uag.CId,
        uag.AuthorIsatIonGroupId,
        rn = ROW_NUMBER() OVER (PARTITION BY uag.[UId], uag.CId, uag.AuthorIsatIonGroupId ORDER BY uag.CId)
    FROM uag
    WHERE uag.[UId] = @UId
        AND uag.IsDeleted = 0
),
cteuc AS
(
    SELECT
        uc.CId,
        cteuag.AuthorIsatIonGroupId,
        uc.[UId],
        i.FirstName + Iif(i.MiddleName IS NOT NULL, ' ' + i.MiddleName + ' ', ' ') + i.Surname AS [AName],
        rn = ROW_NUMBER() OVER (PARTITION BY uc.CId, uc.[UId] ORDER BY uc.ModifiedAt)
    FROM uc
        INNER JOIN cteuag ON cteuag.CId = uc.CId
            AND uc.IsDeleted = 0
        INNER JOIN ui ON ui.[UId] = uc.[UId]
            AND ui.IsDeleted = 0
        INNER JOIN i ON i.PId = ui.IndividualId
),
ctel AS
(
    SELECT
        la.LId,
        p.CId,
        la.[UId],
        rn = ROW_NUMBER() OVER (PARTITION BY la.LId ORDER BY la.DateUpdated DESC)
    FROM la 
        INNER JOIN p ON p.Id = la.PId
            AND p.IsDeleted = 0
            AND la.IsDeleted = 0
            AND la.[UId] IS NOT NULL
        INNER JOIN l ON la.LId = l.Id
            AND l.IsDeleted = 0
)
SELECT
    c.Id AS CId,
    c.[Name] AS CName,
    u.Id AS AId,
    cteuc.AName AS AName,
    ctel.LId AS LId,
    qh.Id AS QhId,
    q.Id AS QId,
    q.IsTrue AS isTrue,
    p.Id AS PId,
    p.[Name] AS PName,
    qi.FinalCalculation AS Calculation
INTO #FilteredData
FROM c
    INNER JOIN cteuc ON cteuc.CId = c.Id
        AND cteuc.Rn = 1
        AND c.IsDeleted = 0
    LEFT OUTER JOIN u ON u.Id = Iif(cteuc.AuthorIsatIonGroupId = 1, @UId, cteuc.[UId])
        AND u.IsDeleted = 0
    LEFT OUTER JOIN ctel ON ctel.CId = c.Id
        AND ctel.Rn = 1
        AND ctel.[UId] = u.Id
    LEFT OUTER JOIN 
    (
        la
        INNER JOIN qla ON qla.LeadActivityId = la.Id
            AND la.IsDeleted = 0
            AND la.ActivityTypeId = 4
        INNER JOIN qh ON qla.QhId = qh.Id
            AND qh.IsDeleted = 0
            AND qh.IsReRated = 0
        LEFT OUTER JOIN 
        (
            q 
            INNER JOIN p ON p.Id = q.PId
                AND q.IsDeleted = 0
                AND p.IsDeleted = 0
        ) ON q.QhId = qh.Id) ON la.[UId] = u.Id
        AND la.LId = ctel.LId
    LEFT OUTER JOIN 
    (
        SELECT
            qi1.QId,
            SUM(Iif(qi1.Calculation = 0, 0, qi1.Calculation + qi1.Extra)) AS FinalCalculation
        FROM qi
        WHERE qi1.IsDeleted = 0
        GROUP BY QId
    ) AS qi ON qi.QId = q.Id

SELECT * FROM #FilteredData

因此我知道這不是用作過濾器的逗號分隔值,也不是前導通配符。

因此,事實證明它可以在另一台筆記本電腦上正常運行,這意味着這與我的筆記本電腦有關。 無論如何,查看注釋,此查詢可能需要大量改進

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM