These two terms in the Predicate Information section indicate when the data source is reduced. Simply, access means only retrieve those records meeting the condition and ignore others. Filter means *after* you already got the data, go through them all and keep those meeting the condition and throw away the others.
access: 直接擷取那些滿足條件的資料,抛棄其他不滿足的資料
filter: 你已經有了一些資料,對這些已經有的資料應用filter,得到滿足filter的資料。
<a href="http://www.itpub.net/forum.php?mod=viewthread&tid=1766289">http://www.itpub.net/forum.php?mod=viewthread&tid=1766289</a>
一:簡要說明
在檢視執行計劃的資訊中,經常會看到兩個謂詞filter和access,它們的差別是什麼,了解了這兩個詞對我們解讀Oracle的執行計劃資訊會有所幫助。
簡單說,執行計劃如果顯示是access,就表示這個謂詞條件的值将會影響資料的通路路徑(表還是索引),而filter表示謂詞條件的值并不會影響資料通路路徑,隻起到過濾的作用。
二:舉例說明
SQL> create table zhou_t (x int , y int );
表已建立。
SQL> set autotrace trace exp;
SQL> select /*+rule*/ * from zhou_t where x=5;
執行計劃
----------------------------------------------------------
Plan hash value: 1395150869
------------------------------------
| Id | Operation | Name |
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS FULL| ZHOU_T |
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("X"=5)
Note
-----
- rule based optimizer used (consider using cbo)
因為表zhou_t沒有建立索引,執行計劃沒有選擇資料通路路徑的餘地,謂詞條件在這裡隻是起到資料過濾的作用,是以使用了filter
如果在表上建立了索引呢?
SQL> create index zhou_t_idx on zhou_t(x,y);
索引已建立。
Plan hash value: 42197324
---------------------------------------
|* 1 | INDEX RANGE SCAN| ZHOU_T_IDX |
1 - access("X"=5)
從上面可以看到,謂詞條件影響到資料通路的路徑------選擇了索引,是以用access
<a href="http://zuoren110.blog.163.com/blog/static/617563201201331427675/">http://zuoren110.blog.163.com/blog/static/617563201201331427675/</a>
SQL> create table t
2 as select rownum r,object_name
3 from dba_objects
4 /
Table created.
SQL> create index t_idx on t(r);
Index created.
SQL> execute dbms_stats.gather_table_stats(user,'t',cascade=>true)
PL/SQL procedure successfully completed.
SQL> set autotrace traceonly explain
SQL> select * from t
2 where r = 10000;
Execution Plan
Plan hash value: 470836197
-------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 1 | 30 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 30 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 1 | | 1 (0)| 00:00:01 |
2 - access("R"=10000)
使用的謂詞是access ,通路的是索引,然後通過rowid 直接取出select結果。
2 where r > 10000 and r < 50000
3 /
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 40001 | 1171K| 88 (2)| 00:00:02 |
|* 1 | TABLE ACCESS FULL| T | 40001 | 1171K| 88 (2)| 00:00:02 |
1 - filter("R"<50000 AND "R">10000)
使用的謂詞是filter 使用的是全表掃描,過濾掉不需要的行。
SQL> select r from t
2 where r > 10000
Plan hash value: 3163761342
------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 55631 | 271K| 42 (3)| 00:00:01 |
|* 1 | INDEX FAST FULL SCAN| T_IDX | 55631 | 271K| 42 (3)| 00:00:01 |
1 - filter("R">10000)
這裡的執行計劃,就有點意思了,使用的是索引掃描(index fast full scan),
但是沒有通過access 指出。可見oracle 決定使用索引掃描,并不一定要通過
access 來告訴我們。在這裡r 可以完全通過讀取索引來獲得所需要的列值,并且
需要檢索索引中的大部分key,是以oracle 決定使用index fast full scan,這種
通路索引的方式會通過multiblocks read 方式讀取索引的 bocks,傳回的結果集
是未經排序的,并且因為讀取了是以的index blocks ,是以需要對index blocks
中的index keys 進行過濾。
SQL> create table emp
2 as select employee_id,first_name,last_name
3 from hr.employees;
SQL> create index emp_idx on emp(employee_id,last_name);
SQL> exec dbms_stats.gather_table_stats(user,'emp',cascade=>true)
SQL> select employee_id,last_name
2 from emp
3 where employee_id < 200 and last_name = 'King'
Plan hash value: 3087982339
----------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 2 | 24 | 1 (0)| 00:00:01 |
|* 1 | INDEX RANGE SCAN| EMP_IDX | 2 | 24 | 1 (0)| 00:00:01 |
1 - access("LAST_NAME"='King' AND "EMPLOYEE_ID"<200)
filter("LAST_NAME"='King')
我上面這個例子也比較有意思,我們在前面建立了一個複合索引,并且在where 子句中
使用了索引中的列。oracle 會根據where 條件通過通路複合索引中的列是否滿足employee_id < 200
如果滿足再根據條件filter 過濾出last_name = 'King' 的index Key。
小結:通過上面的列子,雖然例子不是很經典,但是我覺得已經可以說明。
1、如果oracle 決定使用 index 來獲得結果集,不需要使用access 謂詞告訴我們,我(oracle)使用了index.
2、通過index 通路資料,也有可能需要用到filter 的。
<a href="http://blog.csdn.net/kkdelta/article/details/7938653">http://blog.csdn.net/kkdelta/article/details/7938653</a>