最近优化SQL时 发现一个SQL, select * from t_pro t where
(select count(1) from t_cost ac where data = 'GZXT' and ac.prj_id = t.prj_code) = 0;
我靠 哪位高人写的SQL, 一看就知道存在性能隐患, 一个大坑。
SQL> explain plan for
2 select * from t_pro t3 where not exists (select 1
4 from t_cost ac
5 where data = 'GZXT'
6 and ac.prj_id = t.prj_code);
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 588010636
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Tim
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 582 | 84972 | 11 (10)| 00:
|* 1 | HASH JOIN RIGHT ANTI| | 582 | 84972 | 11 (10)| 00:
|* 2 | TABLE ACCESS FULL | T_COST | 553 | 7189 | 5 (0)| 00:
| 3 | TABLE ACCESS FULL | T_PRO | 582 | 77406 | 5 (0)| 00:
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("AC"."PRJ_ID"="T"."PRJ_CODE")
2 - filter("DATA"='GZXT')
16 rows selected
SQL> explain plan for
2 select * from t_pro t where
3 (select count(1)
4 from t_cost ac
5 where data = 'GZXT'
6 and ac.prj_id = t.prj_code) = 0;
Explained
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 2930289130
--------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time
--------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 582 | 77406 | 1475 (2)| 00:0
|* 1 | FILTER | | | | |
| 2 | TABLE ACCESS FULL | T_PRO | 582 | 77406 | 5 (0)| 00:0
| 3 | SORT AGGREGATE | | 1 | 13 | |
|* 4 | TABLE ACCESS FULL| T_COST | 2 | 26 | 5 (0)| 00:0
--------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter( (SELECT COUNT(*) FROM "T_COST_ACCRUAL" "AC" WHERE
"AC"."PRJ_ID"=:B1 AND "DATA"='GZXT')=0)
4 - filter("AC"."PRJ_ID"=:B1 AND "DATA"='GZXT')
18 rows selected
not exists 用的是hash join 而 第二个是用的 filter 所有第一个效率 远远比第二个效率 高,
统计信息我没有看,
但这里只是比较 hash join 与 FILTER 的效率。 奇怪了 很多人说 exists 的效率 比in 高, 这里我做了测试
从执行计划上面看 起码这个例子效率都差不多。
我看 要看效率上面的问题还是要到执行计划上面看, 才可靠。 而不是死记结论。