【问题标题】:Request Optimization (CTE, multiple LEFT JOIN, WHERE with OR)请求优化(CTE、多个 LEFT JOIN、WHERE 与 OR)
【发布时间】:2021-04-05 16:06:51
【问题描述】:

谁能给我建议如何优化这个请求?

比这个例子中更多的左连接(20+),主要是用外键获取值,有什么优化可能?

CTE 用于创建聚合,但 CTE 表用于主体请求,那么它有用吗?

在主表上具有简单条件的条件和具有多个表的字段的第二个条件 OR 的情况下,是否可以更好地添加具有 3 个字段的最大日期的列并具有简单的第二个条件(没有 OR) ?

SQL Server 2015+

WITH
cte AS 
(
    SELECT 
        e_ofcte.id,
        SUM(CASE WHEN f_ofcte.lib='G' THEN 1 ELSE 0 END) AS n1,
        SUM(CASE WHEN f_ofcte.lib='H' THEN 1 ELSE 0 END) AS n2
    FROM e_ofcte
    INNER JOIN f_ofcte ON f_ofcte.id=e_ofcte.id
    WHERE f_ofcte.lib IN ('G','H')
        AND e_ofcte.date>=DATEFROMPARTS(YEAR(CURRENT_TIMESTAMP)-2,1,1)
    GROUP BY 
        e_ofcte.id
)

SELECT 
    a.id, 
    b.sid, 
    c.sid,
    cte.n1,
    cte.n2
FROM a 
LEFT JOIN cte ON a.id=cte.id 
LEFT JOIN b ON a.id=b.id 
LEFT JOIN c ON a.id=c.id
LEFT JOIN e_ofcte ON a.id=e_ofcte.id
LEFT JOIN i ON a.id=i.id
LEFT JOIN j ON a.id=j.id
LEFT JOIN f_ofcte ON a.id=f_ofcte.id
WHERE a.code='A'
    AND 
        (
        a.date>=>=DATEFROMPARTS(YEAR(CURRENT_TIMESTAMP)-2,1,1)
        OR
        b.date>=>=DATEFROMPARTS(YEAR(CURRENT_TIMESTAMP)-2,1,1)
        OR
        c.date>=>=DATEFROMPARTS(YEAR(CURRENT_TIMESTAMP)-2,1,1)
        )

【问题讨论】:

  • 可以粘贴执行计划吗? brentozar.com/pastetheplan
  • 为什么要加入多个表,但不使用这些表中的任何列(i、j 等)?
  • 使用其他表的列。我将粘贴执行计划。谢谢
  • 您好,由于隐私问题,我将无法粘贴执行计划。
  • 我不知道为什么粘贴执行计划比粘贴 SQL 有更大的隐私问题,但如果是这样的话……你至少可以粘贴完整的 SQL 语句吗?如果有任何常量值让您担心隐私问题,那么您可以将它们替换为 'x' 或类似的东西

标签: sql sql-server optimization query-optimization


【解决方案1】:

如果您将“OR”条件移至 JOIN,它将返回不同的结果。我的回答是“不”,除非你确切地知道自己在做什么。

您可以尝试多种可能的方法来对抗性能:

  1. 如果可以,将 CTE 移至临时表。它使查询更小? 这将有助于优化器提出最佳计划。还有,你 可以分别调两个声部。
  2. 可能在表 A(id,date) 上使用“WHERE”构建过滤索引 code='A'" - 如果过滤记录的数量是 相对较小
  3. 可能在表 f_ofcte(id) 上使用“WHERE”构建过滤索引 库 IN ('G','H')"
  4. 在 (id,date) 的其他表上建立索引
  5. 不确定您是否提供了完整的查询,但看起来如下 部分完全未使用:

LEFT JOIN e_ofcte ON a.id=e_ofcte.id
LEFT JOIN i ON a.id=i.id
LEFT JOIN j ON a.id=j.id
LEFT JOIN f_ofcte ON a.id=f_ofcte.id

【讨论】:

  • 您好,感谢您的回答,我将尝试移动 CTEin 临时表,我是否应该尝试将第一个表与她的 where 条件一起移动到另一个临时表中?我没有通过完整的请求,是的,使用左连接的其他表的字段如 b.sid、c.sid.Thanks
  • 如果表“A”中有一小部分已使用的记录,则创建过滤索引更容易。如果将其放入临时表中,则可能无论如何都必须在其上创建索引
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-02
  • 2017-07-31
  • 1970-01-01
  • 2014-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多