2017-06-14 88 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 

我希望它能帮助你。