SQL> set linesize 200
SQL> set pagesize 200
SQL> explain plan for select * from test1 where owner='SCOTT' or object_id in (select object_id from test2 where owner='SCOTT');
已解释。
SQL> select * from table(dbms_xplan.display());
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1896454807
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6171 | 1247K| 348 (1)| 00:00:05 |
|* 1 | FILTER | | | | | |
| 2 | TABLE ACCESS FULL| TEST1 | 103K| 20M| 348 (1)| 00:00:05 |
|* 3 | TABLE ACCESS FULL| TEST2 | 1 | 30 | 347 (1)| 00:00:05 |
----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("OWNER"='SCOTT' OR EXISTS (SELECT 0 FROM "TEST2" "TEST2"
WHERE "OBJECT_ID"=:B1 AND "OWNER"='SCOTT'))
3 - filter("OBJECT_ID"=:B1 AND "OWNER"='SCOTT')
Note
-----
- dynamic sampling used for this statement (level=2)
已选择21行。
SQL> select count(*) from test1;
COUNT(*)
----------
1006
SQL> select count(*) from test2;
COUNT(*)
----------
87007
SQL> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST'));
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID a23r1uchdaafg, child number 0
-------------------------------------
select * from test1 where owner='SCOTT' or object_id in(select
object_id from test2 where owner='SCOTT')
Plan hash value: 1896454807
--------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
--------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 6 |00:00:05.35 | 1247K|
|* 1 | FILTER | | 1 | | 6 |00:00:05.35 | 1247K|
| 2 | TABLE ACCESS FULL| TEST1 | 1 | 1000 | 1006 |00:00:00.01 | 24 |
|* 3 | TABLE ACCESS FULL| TEST2 | 1000 | 1 | 0 |00:00:05.35 | 1247K|
--------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(("OWNER"='SCOTT' OR IS NOT NULL))
3 - filter(("OBJECT_ID"=:B1 AND "OWNER"='SCOTT'))
Note
-----
- dynamic sampling used for this statement (level=2)
已选择26行。
08-24
2013-08-24:12:04:21 VALID N N N 1
已选择6行。
注意看 A-Rows,Id=2 返回1006条记录 ,
然后 Id=3 执行了1000 次 最后返回7条数据1006-1000=6
那么现在知道了 filter其实就相当于 NESTED LOOPS ,但是又不完全是 NESTED LOOPS
这里我们把离FILTER进的表也叫做驱动表,远的表叫被驱动表。
如果驱动表返回大量数据(比如100W),最后FILTER过滤剩下10W条记录,那么被驱动表就会扫描100W-10W=90W次,这个时候不慢才怪了,逻辑读也就上去了。
大家在看执行计划的时候,看到FILTER就要引起注意了,绝大多数性能问题都是它引发的,所以我为啥说我培训是教你一眼看出性能问题。
注意:看到FILTER不一定它就慢,有时候还非得用FILTER不可,它跑得更快,后面有案例。