Как я могу предотвратить появление Lazy Spool в моем запросе? - PullRequest
0 голосов
/ 18 декабря 2018

Я изо всех сил пытался оптимизировать этот запрос,

 SELECT
                dbo.OE61BLIN.Order_Key
               ,dbo.OE61BLIN.Doc_Type
               ,dbo.OE61BHED.Doc__
               ,dbo.OE61BHED.Inv_Date
               ,dbo.OE61BHED.Cust__
               ,dbo.OE61BLIN.Line_Type
               ,dbo.OE61BLIN.Item__
               ,dbo.OE61BLIN.Description
               ,(CASE
                    WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
                    WHEN dbo.OE61BLIN.Doc_Type = 'C' AND
                        dbo.OE61BLIN.return_to_inventory_ = 1 THEN -dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
                    ELSE 0
                END) AS QTY
               ,(CASE
                    WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Ext_Price
                    WHEN dbo.OE61BLIN.Doc_Type = 'C' THEN -dbo.OE61BLIN.Ext_Price
                    ELSE 0
                END) * (CASE
                    WHEN ISNULL(dbo.OE61BHED.Inv_Disc__, 0) <> 0 THEN 1 - (dbo.OE61BHED.Inv_Disc__ / 100)
                    ELSE 1
                END)
                AS amount
               ,dbo.OE61BHED.Inv_Disc__
               ,dbo.OE61BLIN.ITEM_GROUP
               ,dbo.OE61BLIN.Category
               ,ISNULL(dbo.AR61ACST.intercompany, 0) AS intercompany 
            FROM dbo.OE61BHED
                LEFT OUTER JOIN dbo.AR61ACST
                    ON dbo.OE61BHED.Cust__ = dbo.AR61ACST.Cust__
                RIGHT OUTER JOIN dbo.OE61BLIN
                    ON dbo.OE61BHED.Order_Key = dbo.OE61BLIN.Order_Key
            WHERE (dbo.OE61BLIN.Line_Type = 'R')
            AND isnull(intercompany,0)  != 1
            AND (dbo.OE61BLIN.Doc_Type = 'C'
            OR dbo.OE61BLIN.Doc_Type = 'I')

Полный примерный план выполнения здесь https://www.brentozar.com/pastetheplan/?id=S1htt0rxN

Фактический план Exectuion https://www.brentozar.com/pastetheplan/?id=BymztxLgE

Я использую SQLSentry Plan Explorer, чтобы оптимизировать его, и он предложил мне добавить следующие два индекса, которые у меня есть, но он не сильно улучшается, он только удалил RID Look Up из плана.

 CREATE NONCLUSTERED INDEX [XI_LineTypeDocType_OE61BLIN_12172018]
    ON [dbo].[OE61BLIN] ([Line_Type],[Doc_Type])
    INCLUDE ([Order_Key],[Item__],[Description],[Category],[Return_to_Inventory_],[Unit_Factor],[Qty_Shipped],[Ext_Price],[ITEM_GROUP])

    CREATE INDEX [XI_CustIntercompany_AR67ACST_12172018] ON [GarbageMark].[dbo].[AR61ACST]
    ([Cust__] ASC)
    INCLUDE ([Intercompany])

Я застрял полностьюо том, как решить эту проблему.

Я вижу, что Lazy Spool - самая дорогая операция, но я не знаю, как удалить или заменить.

1 Ответ

0 голосов
/ 18 декабря 2018

К сожалению, вы не ставите префикс intercompany в предложении where с именем таблицы, поэтому в некоторой степени я предполагаю, что изменения вы видите ниже.Я собираюсь предложить вам перестроить запрос, чтобы избежать использования правого внешнего соединения, а затем, возможно, что еще более важно, поместить условие intercompany <> 1 непосредственно в левое соединение, которое исключает использование ISNULL() из предложения where,

SELECT
    dbo.OE61BLIN.Order_Key
  , dbo.OE61BLIN.Doc_Type
  , dbo.OE61BHED.Doc__
  , dbo.OE61BHED.Inv_Date
  , dbo.OE61BHED.Cust__
  , dbo.OE61BLIN.Line_Type
  , dbo.OE61BLIN.Item__
  , dbo.OE61BLIN.Description
  , (CASE
        WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
        WHEN dbo.OE61BLIN.Doc_Type = 'C' AND
            dbo.OE61BLIN.return_to_inventory_ = 1 THEN -dbo.OE61BLIN.Qty_Shipped * dbo.OE61BLIN.Unit_Factor
        ELSE 0
    END)                                   AS QTY
  , (CASE
        WHEN dbo.OE61BLIN.Doc_Type = 'I' THEN dbo.OE61BLIN.Ext_Price
        WHEN dbo.OE61BLIN.Doc_Type = 'C' THEN -dbo.OE61BLIN.Ext_Price
        ELSE 0
    END) * (CASE
        WHEN ISNULL( dbo.OE61BHED.Inv_Disc__, 0 ) <> 0 THEN 1 - (dbo.OE61BHED.Inv_Disc__ / 100)
        ELSE 1
    END)                                   
    AS amount
  , dbo.OE61BHED.Inv_Disc__
  , dbo.OE61BLIN.ITEM_GROUP
  , dbo.OE61BLIN.Category
  , ISNULL( dbo.AR61ACST.intercompany, 0 ) AS intercompany
FROM dbo.OE61BLIN
INNER JOIN dbo.OE61BHED  ON dbo.OE61BLIN.Order_Key = dbo.OE61BHED.Order_Key 
LEFT OUTER JOIN dbo.AR61ACST ON dbo.OE61BHED.Cust__ = dbo.AR61ACST.Cust__ 
                            AND dbo.AR61ACST.intercompany != 1
WHERE dbo.OE61BLIN.Line_Type = 'R'
AND dbo.OE61BLIN.Doc_Type IN ('C','I')
;

Я считаю, что соединение между OE61BLIN и OE61BHED может быть внутренним соединением, если не попытаться использовать левое соединение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...