遗留SELECT语句性能优化咨询:子查询必要性及优化方案
SQL语句优化分析与建议
一、NOT EXISTS子查询的必要性
该子查询是必要的。因为ID并非主键,T1中同一个ID可能存在多条记录:部分记录DATE非空,部分DATE为空。原语句的NOT EXISTS条件用于排除那些在T1中存在DATE为空记录的ID——哪怕该ID同时有DATE非空的记录,也会被过滤,这是业务逻辑要求的一部分,不能直接删除。
二、语句优化方案
原语句存在嵌套子查询重复扫描T1、不必要的DISTINCT计算等问题,优化后的语句如下:
SELECT A.JOB, MIN(A.ID) AS START_ID, MAX(A.ID) AS END_ID, COUNT(*) AS CNT -- ROWID为每条记录唯一标识,无需DISTINCT去重 FROM ( SELECT COPYTO.ID, COPYTO.ROWID AS R, TRUNC((DENSE_RANK() OVER(ORDER BY COPYTO.ID) - 1) / 500000) AS JOB FROM ( -- 预筛选T1中符合条件的ID:无DATE为空记录,且至少有一条DATE非空记录 SELECT ID FROM T1 GROUP BY ID HAVING MAX(DATE) IS NOT NULL AND MIN(DATE) IS NOT NULL ) VALID_T1 JOIN T2 COPYTO ON VALID_T1.ID = COPYTO.ID WHERE COPYTO.DATE IS NULL ) A WHERE A.JOB < 1 GROUP BY A.JOB
优化点说明:
- 合并T1的条件判断:通过GROUP BY + HAVING一次性筛选出符合要求的ID,避免原语句中关联后再做NOT EXISTS子查询的重复扫描,大幅减少IO开销。
- 去除不必要的DISTINCT:ROWID是Oracle中每条记录的唯一物理标识,
COUNT(DISTINCT R)等价于COUNT(*),去掉DISTINCT可减少计算量。 - 简化关联逻辑:先筛选出有效ID集合,再与T2关联,缩小关联的数据范围。
并行提示调整(可选):
原语句的表级并行提示如果不是必须,建议改为全局并行或直接移除:
- 若数据量极大(千万级以上),可在主查询前添加
/*+ PARALLEL(20) */全局并行提示; - 若数据量较小,建议移除并行提示,避免并行调度带来的额外开销。
三、执行计划获取方法(Oracle环境)
获取执行计划可通过以下方式:
- SQLPLUS/PLSQL Developer:执行
SET AUTOTRACE ON EXPLAIN,再运行目标SQL,直接输出执行计划。 - DBMS_XPLAN包:
EXPLAIN PLAN FOR -- 粘贴你的SQL语句 SELECT ...; SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);
- Oracle SQL Developer:选中目标SQL,点击工具栏的"执行计划"按钮(流程图图标)即可查看。
内容的提问来源于stack exchange,提问作者Dani Che
相关产品推荐
相关产品推荐

