sql - 如何防止查询中出现惰性后台打印?

标签 sql t-sql sql-server-2012 query-optimization

我一直在努力优化这个查询,

 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

实际执行计划 https://www.brentozar.com/pastetheplan/?id=BymztxLgE

我使用 SQL Sentry 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 是最昂贵的操作,但我不知道如何删除 或替代。

最佳答案

遗憾的是您没有添加前缀 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 之间的联接可以是内部联接,如果不是,请尝试使用左联接。

关于sql - 如何防止查询中出现惰性后台打印?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53825683/

相关文章:

c# - SQL Server 2012 几何 - 使用 SqlDataAdapter 加载模式

sql - 删除重复记录,只保留最新的一条

sql - 递归 CTE 错误 : Types do not match

sql - 执行SQL遇到的问题

sql - 分组集、汇总但具有多列

database - 在事务中包装 visual studio 数据库单元测试以消除持久的数据库更改

sql - 变长子串

SQL 类似于正则表达式,相当于开始 ^ 和结束 $ 行

php - 在 oxy 中执行 SQL 查询

SQL 如何在 SQL 中将数字转换为具有最小小数位数(动态小数位数)的文本