天天看點

oracle_執行計劃_謂詞資訊和資料擷取(access and filter差別) (轉)

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&amp;tid=1766289">http://www.itpub.net/forum.php?mod=viewthread&amp;tid=1766289</a>

一:簡要說明

在檢視執行計劃的資訊中,經常會看到兩個謂詞filter和access,它們的差別是什麼,了解了這兩個詞對我們解讀Oracle的執行計劃資訊會有所幫助。

簡單說,執行計劃如果顯示是access,就表示這個謂詞條件的值将會影響資料的通路路徑(表還是索引),而filter表示謂詞條件的值并不會影響資料通路路徑,隻起到過濾的作用。

二:舉例說明

SQL&gt; create table zhou_t (x int , y int );

表已建立。

SQL&gt; set autotrace trace exp;

SQL&gt; 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&gt; 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&gt; create table t

  2  as select rownum r,object_name

  3  from dba_objects

  4  /

Table created.

SQL&gt; create index t_idx on t(r);

Index created.

SQL&gt; execute dbms_stats.gather_table_stats(user,'t',cascade=&gt;true)

PL/SQL procedure successfully completed.

SQL&gt; set autotrace traceonly explain

SQL&gt; 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 &gt; 10000 and r &lt; 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"&lt;50000 AND "R"&gt;10000)

使用的謂詞是filter 使用的是全表掃描,過濾掉不需要的行。

SQL&gt; select r from t

  2  where r &gt; 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"&gt;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&gt; create table emp

  2  as select employee_id,first_name,last_name

  3  from hr.employees;

SQL&gt; create index emp_idx on emp(employee_id,last_name);

SQL&gt; exec dbms_stats.gather_table_stats(user,'emp',cascade=&gt;true)

SQL&gt; select employee_id,last_name

  2  from emp

  3  where employee_id &lt; 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"&lt;200)

       filter("LAST_NAME"='King')

我上面這個例子也比較有意思,我們在前面建立了一個複合索引,并且在where 子句中

使用了索引中的列。oracle 會根據where 條件通過通路複合索引中的列是否滿足employee_id &lt; 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>