oracle 这个SELECT可以改进吗?[已关闭]

mftmpeh8  于 2023-08-03  发布在  Oracle
关注(0)|答案(2)|浏览(105)

已关闭。此问题需要details or clarity。它目前不接受回答。
**希望改进此问题?**通过editing this post添加详细信息并阐明问题。

4天前关闭。
此帖子是在3天前编辑并提交审查的。
Improve this question
我发现这个遗留的SELECT语句的性能非常差。列ID不是主键。我该如何改进它?是子查询且不存在(SELECT...真的需要?

SELECT A.JOB,
 MIN(A.ID) AS START_ID,
 MAX(A.ID) AS END_ID,
 COUNT(DISTINCT A.R) AS CNT
  FROM (SELECT /*+ PARALLEL(copyfrom 20) PARALLEL(copyto 20) */
             COPYTO.ID,
             COPYTO.ROWID AS R,
             TRUNC((DENSE_RANK() OVER(ORDER BY COPYTO.ID) - 1) / 500000) AS JOB
              FROM T1 COPYFROM
              JOIN T2 COPYTO
                ON COPYFROM.ID = COPYTO.ID
             WHERE COPYTO.DATE IS NULL
               AND COPYFROM.DATE IS NOT NULL
               AND NOT EXISTS
             (SELECT * FROM T1 COPYFROM
                     WHERE COPYFROM.ID = COPYTO.ID
                       AND COPYFROM.DATE IS NULL)) A
 WHERE A.JOB < 1
 GROUP BY A.JOB

字符串
T1和T2上有指数:

create index idx1 on t1 (id, date);
create index idx2 on t2 (id, date);


我想上传执行计划,但不知道如何?

dtcbnfnu

dtcbnfnu1#

由于查询已经使用了窗口函数,所以真的没有必要使用相关的子查询-您应该能够使用另一个窗口函数(未测试)获得相同的结果:

SELECT A.JOB,
 MIN(A.ID) AS START_ID,
 MAX(A.ID) AS END_ID,
 COUNT(DISTINCT A.R) AS CNT
  FROM (SELECT COPYTO.ID,
             COPYTO.ROWID AS R,
             COPYFROM.DATE as COPYFROM_DATE,
             TRUNC((DENSE_RANK() OVER(ORDER BY COPYTO.ID) - 1) / 500000) AS JOB,
             COUNT(CASE 
                     WHEN COPYFROM.DATE IS NULL THEN 1 
                     ELSE NULL 
                   END) OVER (PARTITION BY COPYTO.ID) AS CNT_NULL_DATES_FOR_THIS_ID
              FROM T1 COPYFROM
              JOIN T2 COPYTO
                ON COPYFROM.ID = COPYTO.ID
             WHERE COPYTO.DATE IS NULL                   
) A
 WHERE A.JOB < 1
   AND A.CNT_NULL_DATES_FOR_THIS_ID = 0
   AND A.COPYFROM_DATE IS NOT NULL
 GROUP BY A.JOB

字符串

  • 更新 * 正如@astentx在他们的评论中指出的那样,由于WHERE ... COPYFROM.DATE IS NOT NULLCOUNT(...)没有按预期工作。我相应地修改了查询(将WHERE子句移到外部SELECT)

SQL小提琴

4ktjp1zp

4ktjp1zp2#

从请求注解中了解到名为ID的列在两个表中都不是唯一的,查询看起来很好。
您希望查找有日期的copyfrom行和没有日期的copyto行。为此,我建议使用以下索引:

create index idx1 on t1 (date, id);
create index idx2 on t2 (date, id);

字符串
然后查询检查是否存在没有ID日期的copyfrom行,因此另一个索引可以发挥作用:

create index idx3 on t1 (id, date);


就这样更好的方法是将表分成两个分区,一个用于空日期,一个用于非空日期。

相关问题