2015-12-31 181 views
1

刪除索引掃描我的微調下面的SQL查詢從執行計劃

SELECT C.zoneId     , 
     Count(DISTINCT J.id)  , 
     Sum(BP.InstalledSubtotal) 
FROM cust C 
     INNER JOIN Jobs J 
       ON J.CustomerId = C.id 
     LEFT OUTER JOIN(SELECT DISTINCT GZZ.ZipAndPostalCodeId, 
             GZZ.GeographicalZoneId, 
             gz.DEALERId 
         FROM GeoZip GZZ 
           INNER JOIN GeographicalZone GZ 
             ON GZZ.GeographicalZoneId = GZ.Id) CGZ 
        ON CGZ.ZipAndPostalCodeId = C.PhysicalZipId 
         AND CGZ.DEALERId = c.DEALERId 
     INNER JOIN BndProduct BP 
       ON BP.TableRowId = J.id 
        AND BP.TableId = 23 
        AND BP.InstalledSubtotal <> 0 
WHERE BP.DateCreated BETWEEN 'Nov 1 2015 12:00AM' AND 'Nov 20 2015 11:59PM' 
     AND (Cast(BP.DateCreated AS DATE) <> Cast(J.ContractDate AS DATE) 
       OR (Cast(BP.DateCreated AS DATE) = Cast(J.ContractDate AS DATE) 
        AND BP.EmployeeId <> J.SalesRepId)) 
     AND (BP.EmployeeId <> 0 
      AND BP.EmployeeId IS NOT NULL) 
     AND (J.SalesRepId <> 0 
      AND J.SalesRepId IS NOT NULL) 
     AND (EXISTS (SELECT 1 
        FROM ServLead ISL 
          INNER JOIN Appts IA 
            ON IA.ServiceLeadId = ISL.id 
          INNER JOIN CalEve IE 
            ON IE.TableId = 1 
             AND IE.TableRowId = IA.id 
          INNER JOIN ApptRst IAR 
            ON IAR.EventId = IE.id 
          INNER JOIN Job IJ 
            ON IJ.AppointmentResultId = IAR.id 
             AND IJ.id = J.id 
        WHERE (ISL.IsTemporary = 0) 
          AND (IA.IsTemporary = 0) 
          AND (IE.IsTemporary = 0) 
          AND (IAR.IsTemporary = 0)) 
       OR J.ProductionTypeId = 2) 
     AND (BP.IsDeleted = 0) 
     AND (C.IsTemporary = 0) 
     AND (J.IsTemporary = 0) 
     AND (C.ZoneId = 0 
       OR 0 = 0) 
     AND (CGZ.GeographicalZoneId = 0 
       OR 0 = 0) 
     AND CASE '0' 
      WHEN 'STATE' THEN C.PhysicalState 
      WHEN '' THEN 0 
      ELSE 0 
      END LIKE 0 
     AND C.DEALERId = 23 
GROUP BY C.zoneId 

請參照執行計劃。

enter image description here

有一個索引掃描。我不知道如何改變它以索引查找。

我試着用下面的提示。

with (forceseek) 

但是當我比較正常的SQL和SQL的結果與提示。普通SQL比使用Hint的SQL執行更好。

請提供任何建議來即興查詢。 目前花了約5至6秒。我試圖減少到1-2秒。

@Devart:我已經實現了你的解決方案,但看起來執行時間相同。

請按照您的要求檢查執行計劃。

enter image description here

enter image description here

+2

你'FROM Object8 Object6 INNER JOIN Object9 Object7'是要鬧事拍攝了很多的樂趣這走樣!這似乎相反的直覺.....爲什麼別名?對我沒有多大意義..... –

+2

因此,在您的情況下索引掃描執行比索引尋求更好:)爲什麼你想在這裏需要索引搜索? –

+1

這也是一個**索引掃描** - SQL Server不掃描整個表 - 只有一個特定的索引。如果該索引很小(例如,只有一列或幾列,只有像INT這樣的小數據類型),這實際上可能非常有效!如果SQL Server查詢優化器選擇了此操作,則它可能比強制索引查找更有效...... –

回答

1
DECLARE @t TABLE (ID INT PRIMARY KEY) 

INSERT INTO @t (ID) 
SELECT /*DISTINCT*/ IJ.id 
FROM ServLead ISL 
JOIN Appts IA ON IA.ServiceLeadId = ISL.id 
JOIN CalEve IE ON IE.TableId = 1 AND IE.TableRowId = IA.id 
JOIN ApptRst IAR ON IAR.EventId = IE.id 
JOIN Job IJ ON IJ.AppointmentResultId = IAR.id 
WHERE ISL.IsTemporary = 0 
    AND IA.IsTemporary = 0 
    AND IE.IsTemporary = 0 
    AND IAR.IsTemporary = 0 

SELECT C.zoneId, 
     COUNT(DISTINCT J.id), 
     SUM(BP.InstalledSubtotal) 
FROM cust C 
JOIN Jobs J ON J.CustomerId = C.id 
--LEFT JOIN (
-- SELECT DISTINCT GZZ.ZipAndPostalCodeId, 
--     GZZ.GeographicalZoneId, 
--     GZ.DEALERId 
-- FROM GeoZip GZZ 
-- JOIN GeographicalZone GZ ON GZZ.GeographicalZoneId = GZ.id 
--) CGZ ON CGZ.ZipAndPostalCodeId = C.PhysicalZipId 
-- AND CGZ.DEALERId = C.DEALERId 
JOIN BndProduct BP ON BP.TableRowId = J.id 
    AND BP.TableId = 23 
    AND BP.InstalledSubtotal <> 0 
WHERE BP.DateCreated BETWEEN '20151101 12:00AM' AND '20151120 11:59PM' 
    AND (
      CAST(BP.DateCreated AS DATE) <> CAST(J.ContractDate AS DATE) 
     OR (
       CAST(BP.DateCreated AS DATE) = CAST(J.ContractDate AS DATE) 
      AND 
       BP.EmployeeId <> J.SalesRepId) 
     ) 
    AND BP.EmployeeId <> 0 
    AND J.SalesRepId <> 0 
    AND (EXISTS (
     SELECT 1 
     FROM @t IJ 
     WHERE IJ.id = J.id 
    ) OR J.ProductionTypeId = 2) 
    AND BP.IsDeleted = 0 
    AND C.IsTemporary = 0 
    AND J.IsTemporary = 0 
    AND (C.ZoneId = 0 OR 0 = 0) 
    --AND (CGZ.GeographicalZoneId = 0 OR 0 = 0) 
    AND C.DEALERId = 23 
GROUP BY C.zoneId 
OPTION(RECOMPILE) 

UPDATE -

CREATE NONCLUSTERED INDEX ix 
    ON dbo.ServLead (id) WHERE IsTemporary = 0 
GO 
CREATE NONCLUSTERED INDEX ix 
    ON dbo.Appts (ServiceLeadId) INCLUDE(id) WHERE IsTemporary = 0 
GO 
CREATE NONCLUSTERED INDEX ix 
    ON dbo.CalEve (TableRowId) INCLUDE(id) WHERE IsTemporary = 0 AND TableId = 1 
GO 
CREATE NONCLUSTERED INDEX ix 
    ON dbo.ApptRst (EventId) INCLUDE(id) WHERE IsTemporary = 0 
GO 
CREATE NONCLUSTERED INDEX ix 
    ON dbo.Job (AppointmentResultId) INCLUDE(id) 
GO 

ALTER TABLE dbo.BndProduct 
    ADD DateCreated_DT AS CAST(DateCreated AS DATE) PERSISTED 
GO 
ALTER TABLE dbo.Jobs 
    ADD ContractDate_DT AS CAST(ContractDate AS DATE) PERSISTED 
GO 

DECLARE @t TABLE (ID INT PRIMARY KEY) 
INSERT INTO @t 
SELECT /*DISTINCT*/ IJ.id 
FROM dbo.ServLead ISL 
JOIN dbo.Appts IA ON IA.ServiceLeadId = ISL.id 
JOIN dbo.CalEve IE ON IE.TableId = 1 AND IE.TableRowId = IA.id 
JOIN dbo.ApptRst IAR ON IAR.EventId = IE.id 
JOIN dbo.Job IJ ON IJ.AppointmentResultId = IAR.id 
WHERE ISL.IsTemporary = 0 
    AND IA.IsTemporary = 0 
    AND IE.IsTemporary = 0 
    AND IAR.IsTemporary = 0 
--OPTION(RECOMPILE) 

DECLARE @c TABLE 
(
    ZipAndPostalCodeId INT, 
    DEALERId INT, 
    GeographicalZoneId INT, 
    PRIMARY KEY (ZipAndPostalCodeId, DEALERId, GeographicalZoneId) 
) 
INSERT INTO @c (ZipAndPostalCodeId, GeographicalZoneId, DEALERId) 
SELECT DISTINCT GZZ.ZipAndPostalCodeId, 
       GZZ.GeographicalZoneId, 
       GZ.DEALERId 
FROM dbo.GeoZip GZZ 
JOIN dbo.GeographicalZone GZ ON GZZ.GeographicalZoneId = GZ.id 

SELECT C.zoneId, 
     COUNT(DISTINCT J.id), 
     SUM(BP.InstalledSubtotal) 
FROM dbo.cust C 
JOIN dbo.Jobs J ON J.CustomerId = C.id 
LEFT JOIN @c CGZ ON CGZ.ZipAndPostalCodeId = C.PhysicalZipId AND CGZ.DEALERId = C.DEALERId 
JOIN dbo.BndProduct BP ON BP.TableRowId = J.id 
WHERE BP.DateCreated BETWEEN '20151101 12:00AM' AND '20151120 11:59PM' 
    AND (
      BP.DateCreated_DT <> J.ContractDate_DT 
     OR (
       BP.DateCreated_DT = J.ContractDate_DT 
      AND 
       BP.EmployeeId <> J.SalesRepId) 
     ) 
    AND BP.EmployeeId <> 0 
    AND BP.TableId = 23 
    AND BP.InstalledSubtotal <> 0 
    AND J.SalesRepId <> 0 
    AND (J.id IN (SELECT t.ID FROM @t t) OR J.ProductionTypeId = 2) 
    AND BP.IsDeleted = 0 
    AND C.IsTemporary = 0 
    AND J.IsTemporary = 0 
    AND (C.ZoneId = 0 OR 0 = 0) 
    AND (CGZ.GeographicalZoneId = 0 OR 0 = 0) 
    AND C.DEALERId = 23 
GROUP BY C.zoneId 
OPTION(RECOMPILE) 
+0

'評論' - 也許是不必要的代碼 – Devart

+0

@NewUser需要去...新年快樂給大家! :) – Devart

+0

新年快樂感謝您的解決方案 – StackUser