Oracle group by 和 OR 查询优化

Posted

技术标签:

【中文标题】Oracle group by 和 OR 查询优化【英文标题】:Oracle group by and OR query optimization 【发布时间】:2020-03-13 05:54:26 【问题描述】:
SELECT BATCH_ID,
  BU_CODE,
  BU_TYPE,
  BATCH_TYPE,
  BATCH_GROUP_ID,
  STATUS,
  UPD_DTIME
FROM BATCH_T
WHERE (BU_CODE, BU_TYPE, BATCH_TYPE, UPD_DTIME) IN
  (SELECT BU_CODE,
    BU_TYPE,
    BATCH_TYPE,
    MAX(UPD_DTIME)
  FROM BATCH_T
  WHERE STATUS = 'CLOSED'
  GROUP BY BU_CODE,
    BU_TYPE,
    BATCH_TYPE
  )
OR UPD_DTIME >= SYSDATE - 5;

如上面没有 OR 条件的 Oracle Query 它给出快速响应,但有 OR 条件它需要这么多时间。能否请您帮助如何提高上述查询的响应时间。

【问题讨论】:

执行计划将有助于确定问题 【参考方案1】:

您需要最近关闭的记录以及过去五天的所有内容。使用窗口函数!

SELECT b.*
FROM (SELECT b.*,
             ROW_NUMBER() OVER (PARTITION BY BU_CODE, BU_TYPE, BATCH_TYPE, STATUS ORDER BY UPD_DTIME DESC) as seqnum
      FROM BATCH_T b
     ) b
WHERE UPD_DTIME >= SYSDATE - 5 OR
      (STATUS = 'CLOSED' AND seqnum = 1);

这应该比使用IN/EXISTS 和聚合的任何方法都快。写起来也比较简单。

【讨论】:

'OR BATCH_ID IN (SELECT BATCH_ID FROM BATCH_T batch JOIN BATCH_GROUP_T batchGroup ON batch.BATCH_GROUP_ID = batchGroup.BATCH_GROUP_ID WHERE batchGroup.STATUS != 'CLOSED')' ** 我需要再添加 1 个 OR 条件对上面的查询,我可以直接添加吗,会不会导致任何性能问题。欢迎提出建议。** @Gangs165700 。 . .您应该能够向此查询添加其他条件。【参考方案2】:

以这样的方式拆分查询,其中应该有AND 条件以获得如下所示的性能增益。

 SELECT BATCH_ID,
  BU_CODE,
  BU_TYPE,
  BATCH_TYPE,
  BATCH_GROUP_ID,
  STATUS,
  UPD_DTIME
FROM BATCH_T
WHERE UPD_DTIME >= SYSDATE - 5

UNION ALL

SELECT BATCH_ID,
  BU_CODE,
  BU_TYPE,
  BATCH_TYPE,
  BATCH_GROUP_ID,
  STATUS,
  UPD_DTIME
FROM BATCH_T
WHERE (BU_CODE, BU_TYPE, BATCH_TYPE, UPD_DTIME) IN
  (SELECT BU_CODE,
    BU_TYPE,
    BATCH_TYPE,
    MAX(UPD_DTIME)
  FROM BATCH_T
  WHERE STATUS = 'CLOSED'
  GROUP BY BU_CODE,
    BU_TYPE,
    BATCH_TYPE
  ) AND NOT UPD_DTIME >= SYSDATE - 5;

【讨论】:

我需要在上面的查询中再添加 1 个 OR 条件,如下所示, 尝试在该新查询中排除上述 2 个查询结果,并将其与上述查询的所有联合包括在内 我可以用 Union 代替 Union All 吗?【参考方案3】:

您可以为 UPD_DTIME 创建索引

【讨论】:

以上是关于Oracle group by 和 OR 查询优化的主要内容,如果未能解决你的问题,请参考以下文章

oracle 优化GROUP BY

mysql group by导致分页重复数据问题

oracle group by 查询 排序

MySQL 查询优化与 group by 和 order by rand

Oracle LISTAGG() 聚合查询用法 GROUP BY 和 PARTITION BY 的使用和比较

实现 GROUP BY oracle 查询导致:不是 Ruby 中的 GROUP BY 表达式