使用子查询我们可以完全访问表,而没有它我们没有。
这是因为优化器将 谓词重写 为 OR EXISTS。您可以在 EXPLAIN PLAN 的 filter 中看到相同的内容。
id in (123) or id in (select 133 from dual) 与id in (123) or id in (55) 不同,当优化器为查询执行创建最佳计划时。优化器重写谓词中的子查询。
or id in (select 133 from dual) 改写为 OR EXISTS (SELECT 0 FROM "SYS"."DUAL""DUAL" WHERE :B1=133))
例如,
案例#1
SQL> EXPLAIN PLAN FOR
2 SELECT * FROM emp WHERE empno = 7369 or empno = 7499;
Explained.
SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 2355049923
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 78 | 2 (0)| 00:00:01 |
| 1 | INLIST ITERATOR | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| EMP | 2 | 78 | 2 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | PK_EMP | 2 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("EMPNO"=7369 OR "EMPNO"=7499)
15 rows selected.
案例#2
SQL> EXPLAIN PLAN FOR
2 SELECT * FROM emp WHERE empno = 7369 OR empno IN(SELECT 7499 FROM dual);
Explained.
SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Plan hash value: 3969125370
---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 78 | 3 (0)| 00:00:01 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| EMP | 14 | 546 | 3 (0)| 00:00:01 |
|* 3 | FILTER | | | | | |
| 4 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
---------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMPNO"=7369 OR EXISTS (SELECT 0 FROM "SYS"."DUAL"
"DUAL" WHERE :B1=7499))
3 - filter(:B1=7499)
18 rows selected.
因此,您会看到查询被重写,过滤器被应用为
filter("EMPNO"=7369 OR EXISTS (SELECT 0 FROM "SYS"."DUAL"
"DUAL" WHERE :B1=7499))**
现在,让我们执行重写的查询。修改后:
SQL> EXPLAIN PLAN FOR
2 SELECT * FROM emp
3 WHERE EMPNO =7369 OR EXISTS (SELECT 0 FROM DUAL WHERE :B1=7499);
Explained.
SQL>
SQL> SELECT * FROM TABLE(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
Plan hash value: 2411523692
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 2 | 78 | 3 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMP | 2 | 78 | 3 (0)| 00:00:01 |
|* 2 | FILTER | | | | | |
| 3 | FAST DUAL | | 1 | | 2 (0)| 00:00:01 |
--------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EMPNO"=7369 OR EXISTS (SELECT 0 FROM "SYS"."DUAL"
"DUAL" WHERE TO_NUMBER(:B1)=7499))
2 - filter(TO_NUMBER(:B1)=7499)
17 rows selected.
SQL>
因此,您现在可以看到谓词重写和相同的修改查询具有相似的解释计划,并执行 FULL TABLE SCAN。