2017-06-14 86 views
0

你有如何加速比這個查詢的一些想法:如何加快此查詢?

SELECT Vosol = (CASE WHEN EXISTS (SELECT Id 
            FROM trs.CollectionHeaderView AS chv 
            WHERE chv.ItemNum = itm.ItemNum 
              AND chv.CollectionType = '1') 
         THEN ISNULL(itm.Amount, 0) 
         ELSE 0 
        END) , 
     Vakhast = (CASE WHEN EXISTS (SELECT Id 
             FROM  trs.CollectionHeaderView AS chv 
             WHERE chv.ItemNum = itm.ItemNum 
               AND chv.CollectionType = '2') 
         THEN ISNULL(itm.Amount, 0) 
         ELSE 0 
        END) 
FROM trs.TrsDocRcvItem AS itm 
     LEFT JOIN trs.TrsDocRcvHeader AS hdr ON itm.HeaderRef = hdr.Id 
     LEFT JOIN acc.DL AS dl ON dl.Id = hdr.DLRef 
     LEFT JOIN trs.TrsDocType AS docType ON docType.Id = hdr.DocTypeRef 
     INNER JOIN sle.SleCustomer AS customer ON customer.DLRef = dl.Id 
     LEFT JOIN trs.AccOperation AS operation ON operation.Id = itm.AccOperationRef 
WHERE hdr.DocTypeRef NOT IN (1141, 1142, 1241, 1242) 
     AND (hdr.State = '1' 
       OR hdr.State = '2' 
      ) 
     AND operation.StateType = '1' 

我試圖優化SQL查詢現在約需6秒鐘執行。 我還能做些什麼來加速此查詢? 我正在使用Microsoft Sql Server。

+5

你有一個執行計劃,所以我們可以看到瓶頸? – MarkD

+1

你爲什麼加入'acc.DL'和'sle.SleCustomer'。它真的用於過濾記錄嗎? –

+0

是的,我用過它。 –

回答

2

使用OUTER APPLY刪除兩個相關的子查詢。

SELECT Vosol = CASE WHEN chv1 IS NOT NULL THEN Isnull(itm.Amount, 0) ELSE 0 END, 
     Vakhast = CASE WHEN chv2 IS NOT NULL THEN Isnull(itm.Amount, 0) ELSE 0 END 
FROM trs.TrsDocRcvItem AS itm 
     INNER JOIN trs.TrsDocRcvHeader AS hdr 
       ON itm.HeaderRef = hdr.Id 
     --LEFT JOIN acc.DL AS dl 
     --  ON dl.Id = hdr.DLRef 
     --LEFT JOIN trs.TrsDocType AS docType 
      -- ON docType.Id = hdr.DocTypeRef 
     --INNER JOIN sle.SleCustomer AS customer 
     --  ON customer.DLRef = dl.Id 
     INNER JOIN trs.AccOperation AS operation 
       ON operation.Id = itm.AccOperationRef 
     OUTER apply (SELECT Max(CASE WHEN chv.CollectionType = '1' THEN id END) AS chv1, 
          Max(CASE WHEN chv.CollectionType = '2' THEN id END) AS chv2 
        FROM trs.CollectionHeaderView AS chv 
        WHERE chv.ItemNum = itm.ItemNum 
          AND chv.CollectionType IN ('1', '2')) oa 
WHERE hdr.DocTypeRef NOT IN (1141, 1142, 1241, 1242) 
     AND hdr.State IN ('1', '2') 
     AND operation.StateType = '1' 

我已經註釋掉acc.DLsle.SleCustomer表。除了過濾記錄之外,我沒有看到它的任何用處。如果你真的需要它,然後取消它的評論。

另外我已經評論trs.TrsDocType表,它再次沒有用處。除非它與trs.TrsDocRcvHeader表有一對多的關係。如果它有一對多的關係,那麼結果只是無緣無故地被重複,因爲您沒有從trs.TrsDocType表中選擇任何內容。


如果查詢運行緩慢,那麼您需要在涉及的表上創建Indexes。還要確保statistics均達到最新


分析你的執行計劃,TrsDocRcvItem表費用47%後。創建於TrsDocRcvItem表中的索引應該幫助查詢

CREATE NONCLUSTERED INDEX NIX_TrsDocRcvItem 
ON [Trs].[TrsDocRcvItem] (AccOperationRef,ItemNum,HeaderRef) 
INCLUDE (Amount) 

建議指數從您發佈

CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>] 
ON [Trs].[TrsDocRcvItem] ([AccOperationRef]) 
INCLUDE ([ItemNum],[Amount],[HeaderRef]) 
+0

感謝您的幫助..我的查詢結果是2636行,但此查詢退回3033行。 –

+0

@ElhamAzadfar - 取消註釋連接 –

1
執行計劃
SELECT Vosol = (CASE WHEN EXISTS (SELECT Id 
            FROM trs.CollectionHeaderView AS chv 
            WHERE chv.ItemNum = itm.ItemNum 
              AND chv.CollectionType = '1') 
         THEN ISNULL(itm.Amount, 0) 
         ELSE 0 
        END) , 
     Vakhast = (CASE WHEN EXISTS (SELECT Id 
             FROM  trs.CollectionHeaderView AS chv 
             WHERE chv.ItemNum = itm.ItemNum 
               AND chv.CollectionType = '2') 
         THEN ISNULL(itm.Amount, 0) 
         ELSE 0 
        END) 
FROM trs.TrsDocRcvItem AS itm 
     INNER JOIN 
     (
    SELECT * FROM trs.TrsDocRcvHeader 
    WHERE DocTypeRef NOT IN (1141, 1142, 1241, 1242) 
       AND (State = '1' OR State = '2') 

     ) hdr ON itm.HeaderRef = hdr.Id 
     LEFT JOIN acc.DL AS dl ON dl.Id = hdr.DLRef 
     LEFT JOIN trs.TrsDocType AS docType ON docType.Id = hdr.DocTypeRef 
     INNER JOIN sle.SleCustomer AS customer ON customer.DLRef = dl.Id 
     INNER JOIN 
     (SELECT * FROM trs.AccOperation WHERE StateType = '1' 
     ) operation operation.Id = itm.AccOperationRef 

可以更換

WHERE hdr.DocTypeRef NOT IN (1141, 1142, 1241, 1242) 
     AND (hdr.State = '1' 
       OR hdr.State = '2' 
      ) 
     AND operation.StateType = '1' 

INNER JOIN 
     (
    SELECT * FROM trs.TrsDocRcvHeader 
    WHERE DocTypeRef NOT IN (1141, 1142, 1241, 1242) 
       AND (State = '1' OR State = '2') 

     ) hdr ON itm.HeaderRef = hdr.Id 

INNER JOIN 
     (SELECT * FROM trs.AccOperation WHERE StateType = '1' 
     ) operation operation.Id = itm.AccOperationRef 

我希望它能幫助你。