首页 > 解决方案 > 仅对 Where IN 子句中的特定值进行慢速查询

问题描述

我想知道是否有人在以下查询中遇到过这种行为,如果我在“i.InspectionTypeID IN (x)”上进行过滤,如果 x 导致大量(如大约 600 000 的整个结果集的大约 2/3)即使没有结果也需要更长的时间才能返回(15-30 秒 vs 立即)。如果有帮助,我可以包含查询和执行计划。我可以看到查询之间的一些差异,但不知道如何重构以改进它。我们在其他地方应该(并且已经)提高性能的地方有索引,但我似乎被困在这个地方。索引似乎不会影响性能。至少我试过了。

慢查询计划:https ://www.brentozar.com/pastetheplan/?id=SyBDgxSeO

编辑:新计划并根据@charlieface 的建议更新了查询

这是查询:

declare @currentUserID int = 1018
declare @currentCompanyID int = 43
declare @status int = 0
declare @pageSize int = 2147483647
declare @pageNumber int = 1

                    
                    DECLARE @notPreferredAssetIDsTable TABLE (id INT)
                    INSERT INTO @notPreferredAssetIDsTable
                    SELECT RecordID FROM SettingList sl 
                    WHERE SettingID = (SELECT TOP 1 ID FROM Setting 
                                        WHERE SystemUserID = @currentUserID AND Name = 'Preferred Assets' AND Status = @status)
                    AND Value = '0'
                    AND Status = @status 
                    SELECT i.ID As ID, a.AssetTypeID, at.Name as AssetTypeName, a.Code as AssetCode, a.Name as AssetName, CASE WHEN sections.SectionCount = 1 THEN cr.SectionName ELSE '' END as SectionName, c.Name as ContractName, reg.Name as RegionName, i.Carriageway, 
                           startStatus.StatusDate as StartDate, startPoint.Name as StartPointName, i.ChainageFrom, 
                           CASE WHEN i.Carriageway IS NULL THEN NULL ELSE i.ChainageFrom - (CASE WHEN i.Carriageway = 0 THEN startPoint.Forward ELSE startPoint.Reverse END) END StartDistancePast,
                           completedStatus.StatusDate As EndDate, endPoint.Name as EndPointName, i.ChainageTo,
                           CASE WHEN i.Carriageway IS NULL THEN NULL ELSE i.ChainageTo - (CASE WHEN i.Carriageway = 0 THEN endPoint.Forward ELSE endPoint.Reverse END) END EndDistancePast,
                               CASE WHEN i.Carriageway IS NULL THEN '' ELSE (CASE WHEN (ISNULL(OtherDirectionInspection.ID, 0) > 0) THEN 'Forward/Reverse'
                                                                                  WHEN i.Carriageway = 0 THEN 'Forward' ELSE 'Reverse' END) END as CarriagewayName,
                           dbo.GetInspectionTypeNamesForInspectionID(i.ID) AS InspectionTypeName, JobCount.Total As JobCount, i.CreatedDate, 
                           CreatedUserName.DisplayName as CreatedUserName, AssignedUserName.DisplayName as AssignedUserName,
                           i.Comments, i.EntireRoad, i.PlannedDate, latestStatus.InspectionStatus AS LatestInspectionStatus, completedStatus.StatusDate AS CompletedDate, it.CompanyID as InspectionTypeCompanyID, i.ContractID, i.InspectionTypeID, sections.SectionCount,
                           it.Category as InspectionTypeCategory, latestStatus.ModifiedDeviceID as DeviceID, latestStatus.ModifiedUserID as LatestStatusModifiedUserID, i.JobID, i.CapitalWorkID, cw.Name as CapitalWorkName, AssignedUser.Name as AssignedUserEmail, 
                           InspectionRouteName.Name as InspectionRouteName, i.InspectionGroupID,
                           il.Location AS InspectionLocation, 
                           i.OtherDirectionInspectionID , CustomText1 , CustomBit1 , CustomDate1 , CustomNumber1 , CustomReferenceItemID1 , CustomText2 , CustomBit2 , CustomDate2 , CustomNumber2 , CustomReferenceItemID2 , CustomText3 , CustomBit3 , CustomDate3 , CustomNumber3 , CustomReferenceItemID3 , CustomText4 , CustomBit4 , CustomDate4 , CustomNumber4 , CustomReferenceItemID4 , CustomText5 , CustomBit5 , CustomDate5 , CustomNumber5 , CustomReferenceItemID5 , CustomText6 , CustomBit6 , CustomDate6 , CustomNumber6 , CustomReferenceItemID6 , CustomText7 , CustomBit7 , CustomDate7 , CustomNumber7 , CustomReferenceItemID7 , CustomText8 , CustomBit8 , CustomDate8 , CustomNumber8 , CustomReferenceItemID8 , CustomText9 , CustomBit9 , CustomDate9 , CustomNumber9 , CustomReferenceItemID9 , CustomText10 , CustomBit10 , CustomDate10 , CustomNumber10 , CustomReferenceItemID10 , CustomText11 , CustomBit11 , CustomDate11 , CustomNumber11 , CustomReferenceItemID11 , CustomText12 , CustomBit12 , CustomDate12 , CustomNumber12 , CustomReferenceItemID12 , CustomText13 , CustomBit13 , CustomDate13 , CustomNumber13 , CustomReferenceItemID13 , CustomText14 , CustomBit14 , CustomDate14 , CustomNumber14 , CustomReferenceItemID14 , CustomText15 , CustomBit15 , CustomDate15 , CustomNumber15 , CustomReferenceItemID15 , CustomText16 , CustomBit16 , CustomDate16 , CustomNumber16 , CustomReferenceItemID16 , CustomText17 , CustomBit17 , CustomDate17 , CustomNumber17 , CustomReferenceItemID17 , CustomText18 , CustomBit18 , CustomDate18 , CustomNumber18 , CustomReferenceItemID18 , CustomText19 , CustomBit19 , CustomDate19 , CustomNumber19 , CustomReferenceItemID19 , CustomText20 , CustomBit20 , CustomDate20 , CustomNumber20 , CustomReferenceItemID20 , CustomText21 , CustomBit21 , CustomDate21 , CustomNumber21 , CustomReferenceItemID21 , CustomText22 , CustomBit22 , CustomDate22 , CustomNumber22 , CustomReferenceItemID22 , CustomText23 , CustomBit23 , CustomDate23 , CustomNumber23 , CustomReferenceItemID23 , CustomText24 , CustomBit24 , CustomDate24 , CustomNumber24 , CustomReferenceItemID24 , CustomText25 , CustomBit25 , CustomDate25 , CustomNumber25 , CustomReferenceItemID25 , CustomText26 , CustomBit26 , CustomDate26 , CustomNumber26 , CustomReferenceItemID26 , CustomText27 , CustomBit27 , CustomDate27 , CustomNumber27 , CustomReferenceItemID27 , CustomText28 , CustomBit28 , CustomDate28 , CustomNumber28 , CustomReferenceItemID28 , CustomText29 , CustomBit29 , CustomDate29 , CustomNumber29 , CustomReferenceItemID29 , CustomText30 , CustomBit30 , CustomDate30 , CustomNumber30 , CustomReferenceItemID30 , CustomText31 , CustomBit31 , CustomDate31 , CustomNumber31 , CustomReferenceItemID31 , CustomText32 , CustomBit32 , CustomDate32 , CustomNumber32 , CustomReferenceItemID32 , CustomText33 , CustomBit33 , CustomDate33 , CustomNumber33 , CustomReferenceItemID33 , CustomText34 , CustomBit34 , CustomDate34 , CustomNumber34 , CustomReferenceItemID34 , CustomText35 , CustomBit35 , CustomDate35 , CustomNumber35 , CustomReferenceItemID35 , CustomText36 , CustomBit36 , CustomDate36 , CustomNumber36 , CustomReferenceItemID36 , CustomText37 , CustomBit37 , CustomDate37 , CustomNumber37 , CustomReferenceItemID37 , CustomText38 , CustomBit38 , CustomDate38 , CustomNumber38 , CustomReferenceItemID38 , CustomText39 , CustomBit39 , CustomDate39 , CustomNumber39 , CustomReferenceItemID39 , CustomText40 , CustomBit40 , CustomDate40 , CustomNumber40 , CustomReferenceItemID40 , CustomText41 , CustomBit41 , CustomDate41 , CustomNumber41 , CustomReferenceItemID41 , CustomText42 , CustomBit42 , CustomDate42 , CustomNumber42 , CustomReferenceItemID42 , CustomText43 , CustomBit43 , CustomDate43 , CustomNumber43 , CustomReferenceItemID43 , CustomText44 , CustomBit44 , CustomDate44 , CustomNumber44 , CustomReferenceItemID44 , CustomText45 , CustomBit45 , CustomDate45 , CustomNumber45 , CustomReferenceItemID45 , CustomText46 , CustomBit46 , CustomDate46 , CustomNumber46 , CustomReferenceItemID46 , CustomText47 , CustomBit47 , CustomDate47 , CustomNumber47 , CustomReferenceItemID47 , CustomText48 , CustomBit48 , CustomDate48 , CustomNumber48 , CustomReferenceItemID48 , CustomText49 , CustomBit49 , CustomDate49 , CustomNumber49 , CustomReferenceItemID49 , CustomText50 , CustomBit50 , CustomDate50 , CustomNumber50 , CustomReferenceItemID50 
                    FROM Inspection i
                    INNER JOIN InspectionType it On i.InspectionTypeID = it.ID
                    INNER JOIN SystemUser CreatedUser On CreatedUser.ID = i.CreatedUserID 
                    INNER JOIN Contract c On i.ContractID = c.ID
                    INNER JOIN Region reg On c.RegionID = reg.ID
                    INNER JOIN InspectionLocation il ON il.InspectionID = i.ID 
                    LEFT OUTER JOIN Asset a On i.AssetID = a.ID 
                    LEFT OUTER JOIN SystemUser AssignedUser On AssignedUser.ID = i.AssignedUserID 
                    LEFT OUTER JOIN Road r On i.RoadID = r.ID
                    LEFT OUTER JOIN AssetType at On it.AssetTypeID = at.ID
                    LEFT OUTER JOIN Point startPoint On i.StartPointID = startPoint.ID
                    LEFT OUTER JOIN Point endPoint On i.EndPointID = endPoint.ID
                    LEFT OUTER JOIN CapitalWork cw On i.CapitalWorkID = cw.ID
                    CROSS APPLY dbo.GetNameForUser_Inline(i.CreatedUserID, i.ContractID, @currentCompanyID, 0) As CreatedUserName
                    OUTER APPLY dbo.GetNameForUser_Inline(i.AssignedUserID, i.ContractID, @currentCompanyID, 0) As AssignedUserName
                    OUTER APPLY 
                    (
                         SELECT TOP 1 SectionName
                         FROM ContractRoad cr
                         WHERE cr.RoadID = r.ID
                         AND cr.ContractID = i.ContractID
                         AND ((i.Carriageway = 0 AND i.ChainageFrom < cr.ChainageToForward AND cr.ChainageFromForward < i.ChainageTo)
                            OR (i.Carriageway = 1 AND i.ChainageFrom < cr.ChainageFromReverse AND cr.ChainageToReverse < i.ChainageTo))
                         AND cr.Status = @status
                    ) cr
                    OUTER APPLY 
                    (
                         SELECT count(SectionName) as SectionCount
                         FROM ContractRoad cr
                         WHERE cr.RoadID = r.ID
                         AND cr.ContractID = i.ContractID
                         AND ((i.Carriageway = 0 AND i.ChainageFrom < cr.ChainageToForward AND cr.ChainageFromForward < i.ChainageTo)
                            OR (i.Carriageway = 1 AND i.ChainageFrom < cr.ChainageFromReverse AND cr.ChainageToReverse < i.ChainageTo))
                         AND cr.Status = @status
                    ) sections
                    OUTER APPLY
                    (
                         SELECT TOP 1 StatusDate, LocalTime.LocalTime as StatusDateLocal
                         FROM InspectionStatus
                         CROSS APPLY tzdb.UtcToLocal_Inline(StatusDate, 'Australia/Sydney') as LocalTime
                         WHERE Status = @status
                         AND InspectionID = i.ID
                         AND InspectionStatus = 1
                         ORDER BY StatusDate
                    ) startStatus
                    OUTER APPLY
                    (
                         SELECT TOP 1 StatusDate, LocalTime.LocalTime as StatusDateLocal
                         FROM InspectionStatus
                         CROSS APPLY tzdb.UtcToLocal_Inline(StatusDate, 'Australia/Sydney') as LocalTime
                         WHERE Status = @status
                         AND InspectionID = i.ID
                         AND InspectionStatus = 5
                         ORDER BY StatusDate
                    ) completedStatus
                    OUTER APPLY
                    (
                         SELECT TOP 1 ID, StatusDate, InspectionStatus, ModifiedDeviceID, ModifiedUserID
                         FROM InspectionStatus 
                         WHERE Status = @status AND InspectionStatus.InspectionStatus <> 7
                         AND InspectionID = i.ID
                         ORDER BY CASE WHEN InspectionStatus.InspectionStatus = 6 THEN 1 ELSE 0 END, StatusDate DESC
                    ) latestStatus
                    OUTER APPLY
                    (
                         SELECT COUNT(ID) As Total FROM Job
                         WHERE InspectionID = i.ID
                         AND ParentJobID IS NULL
                         AND Status = @status
                    ) JobCount 
                    OUTER APPLY 
                    (
                         SELECT i2.ID 
                         FROM dbo.Inspection i2 
                         WHERE i2.OtherDirectionInspectionID = i.ID 
                         AND Status = @status 
                    ) OtherDirectionInspection
                    OUTER APPLY
                    (
                         SELECT TOP 1 ir.Name FROM InspectionRoute ir
                         INNER JOIN InspectionGroup ig ON ig.InspectionRouteID = ir.ID
                         WHERE ir.Status = 0
                         AND ir.CompanyID = 43
                         AND ig.Status = 0
                         AND ig.ID = i.InspectionGroupID
                    ) InspectionRouteName
                    
                    
WHERE i.Status = 0 AND i.ParentInspectionID IS NULL 
 AND il.Status = 0 
 --AND ((i.AssetID IS NOT NULL AND i.AssetID NOT IN (SELECT ID FROM @notPreferredAssetIDsTable)) OR i.AssetID IS NULL) 
 AND it.Category <> 2 
 AND c.IsArchived = 0 
 AND it.AssetTypeID = 3 AND a.AssetTypeID IS NOT NULL AND a.AssetTypeID = 3
 AND i.InspectionTypeID IN (3)
 AND i.ContractID IN (90,118) 
 AND (latestStatus.InspectionStatus IN (5,6,1,2,3) OR completedStatus.StatusDate IS NOT NULL  OR latestStatus.InspectionStatus IS NULL)
 AND ((completedStatus.StatusDateLocal >= '2021-02-01 00:00:00' AND completedStatus.StatusDateLocal <= '2021-02-05 23:59:59') OR (i.PlannedDate >= '2021-02-01 00:00:00' AND i.PlannedDate <= '2021-02-05 23:59:59') OR (i.CreatedDate >= '2021-02-01 00:00:00' AND i.CreatedDate <= '2021-02-05 23:59:59' AND (latestStatus.InspectionStatus not in (6, 5) OR latestStatus.InspectionStatus IS NULL)))
 AND ((CASE WHEN i.AssignedUserID IS NULL THEN CreatedUser.CompanyID ELSE AssignedUser.CompanyID END = 43) OR (CASE WHEN i.AssignedUserID IS NULL THEN CreatedUser.CompanyID ELSE AssignedUser.CompanyID END = 1 
                                            AND i.ContractID IN (90,118)) OR (CASE WHEN i.AssignedUserID IS NULL THEN CreatedUser.CompanyID ELSE AssignedUser.CompanyID END = 79 
                                            AND i.ContractID IN (90)) OR (CASE WHEN i.AssignedUserID IS NULL THEN CreatedUser.CompanyID ELSE AssignedUser.CompanyID END = 80 
                                            AND i.ContractID IN (90)) OR (CASE WHEN i.AssignedUserID IS NULL THEN CreatedUser.CompanyID ELSE AssignedUser.CompanyID END = 81 
                                            AND i.ContractID IN (90)) OR (CASE WHEN i.AssignedUserID IS NULL THEN CreatedUser.CompanyID ELSE AssignedUser.CompanyID END = 82 
                                            AND i.ContractID IN (90))) 
ORDER BY ID 
                    OFFSET @pageSize * (@pageNumber - 1) ROWS
                    FETCH NEXT @pageSize ROWS ONLY 
                    OPTION (RECOMPILE)

标签: sql-server

解决方案


推荐阅读