此脚本不依赖统计信息。
当 where 子查询没能 unnest,执行计划中就会出现 FILTER,对于此类 SQL,我们应该在上线之前对其进行改写,避免执行计划中出现 FILTER,以下脚本可以抓出 where 子查询没能 unnest 的 SQL。
select parsing_schema_name schema, sql_id, sql_textfrom v$sqlwhere parsing_schema_name = 'SCOTT'and (sql_id, child_number) in(select sql_id, child_numberfrom v$sql_planwhere operation = 'FILTER'and filter_predicates like '%IS NOT NULL%'minusselect sql_id, child_numberfrom v$sql_planwhere object_owner = 'SYS');
我们在 Scott 账户中运行如下 SQL 并且查看执行计划。
select *from deptwhere exists (select nullfrom empwhere dept.deptno = emp.deptnostart with empno = 7698connect by prior empno = mgr);
DEPTNO DNAME LOC---------- ---------- ---------------------------------------30 SALES CHICAGOElapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 4210865686-------------------------------------------------------------------------------------| Id|Operation |Name|Rows|Bytes| Cost(%CPU)|Time |-------------------------------------------------------------------------------------| 0|SELECT STATEMENT | | 1| 20| 9 (0)|00:00:01||* 1| FILTER | | | | | || 2| TABLE ACCESS FULL |DEPT| 4| 80| 3 (0)|00:00:01||* 3| FILTER | | | | | ||* 4| CONNECT BY NO FILTERING WITH SW (UNIQUE)| | | | | || 5| TABLE ACCESS FULL |EMP | 14| 154| 3 (0)|00:00:01|-------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------1 - filter( EXISTS (SELECT 0 FROM "EMP" "EMP" WHERE "EMP"."DEPTNO"=:B1 START WITH"EMPNO"=7698 CONNECT BY "MGR"=PRIOR "EMPNO"))3 - filter("EMP"."DEPTNO"=:B1)4 - access("MGR"=PRIOR "EMPNO")filter("EMPNO"=7698)Statistics----------------------------------------------------------0 recursive calls0 db block gets36 consistent gets0 physical reads0 redo size550 bytes sent via SQL*Net to client419 bytes received via SQL*Net from client2 SQL*Net roundtrips to/from client8 sorts (memory)0 sorts (disk)1 rows processed
以上 SQL 执行计划中出现了 FILTER,我们通过脚本抓出走了 FILTER 的 SQL。
select parsing_schema_name schema, sql_id, sql_textfrom v$sqlwhere parsing_schema_name = 'SCOTT'and (sql_id, child_number) in(select sql_id, child_numberfrom v$sql_planwhere operation = 'FILTER'and filter_predicates like '%IS NOT NULL%'minusselect sql_id, child_numberfrom v$sql_planwhere object_owner = 'SYS');
SCHEMA SQL_ID SQL_TEXT---------- --------------- ---------------------------------------------SCOTT 8rmn2fn149y2z select * from dept where exists (select null from empwhere dept.deptno = emp.deptno start with empno = 7698 connect by prior empno = mgr)
