目標SQL所需要訪問的數據一般存儲在表裡,而ORACLE訪問表中的數據有兩種方法:一種是直接訪問表,一種是先訪問索引,在回表(當然,如果目標SQL所要訪問的數據只通過訪問相關的索引就可以得到,那麼就不需要回表了)。
ORACLE訪問表的方法:一種全表掃描,另一種是ROWID掃描。
全表掃描是指ORACLE在訪問表的時候,會從該表所占用的第一個區(extent)的第一個塊(block)開始掃描,一直掃描到該表的高水位線(HWM,HICH WATER MARK),這段范圍內所有的數據塊ORACLE都要必須讀到。當然,ORACLE會對這期間讀到的所有數據施加目標SQL的WHRER條件中指定的過濾條件,最後返回只滿足條件的數據。全表掃描可以用多塊讀的屬性。
ROWID掃描時指ORACLE在訪問目標表裡的數據時,直接通過數據所在的ROWID去定位並訪問這些數據。ROWID表示的是ORACLE中的數據行距離所在的物理存儲地址,也就是說ROWID實際上是和ORACLE中數據塊裡的行記錄一一對應。從嚴格意義上說,ORACLE中的ROWID掃描有兩層含義:一種是用戶在SQL語句中輸入的ROWID的值直接去訪問對應的數據行記錄;另外一種是先去訪問相關的索引,然後根據訪問的索引得到的ROWID再回表去訪問對應的數據行記錄。
一,ROWID掃描
ROWID是ORACLE數據庫裡的一個偽列,在實際的表塊中並不存在該列。下面我們來看一個使用ROWID偽列和DBMS_ROWID包實例。
SQL> set linesize 180
SQL> select employee_id,first_name,rowid,dbms_rowid.rowid_relative_fno(rowid) || '_' ||
dbms_rowid.rowid_block_number(rowid) || '_' || dbms_rowid.rowid_row_number(rowid)
location from emp_temp where manager_id=100; 2 3
EMPLOYEE_ID FIRST_NAME ROWID LOCATION
----------- -------------------- ------------------ --------------------------------------------------------------------------------------------------------------------------
201 Michael AAAM0YAAEAAAAGEAAD 4_388_3
101 Neena AAAM0YAAEAAAAGEAAK 4_388_10
102 Lex AAAM0YAAEAAAAGEAAL 4_388_11
114 Den AAAM0YAAEAAAAGEAAX 4_388_23
120 Matthew AAAM0YAAEAAAAGEAAd 4_388_29
121 Adam AAAM0YAAEAAAAGEAAe 4_388_30
122 Payam AAAM0YAAEAAAAGEAAf 4_388_31
123 Shanta AAAM0YAAEAAAAGEAAg 4_388_32
124 Kevin AAAM0YAAEAAAAGEAAh 4_388_33
145 John AAAM0YAAEAAAAGEAA2 4_388_54
146 Karen AAAM0YAAEAAAAGEAA3 4_388_55
147 Alberto AAAM0YAAEAAAAGEAA4 4_388_56
148 Gerald AAAM0YAAEAAAAGEAA5 4_388_57
149 Eleni AAAM0YAAEAAAAGEAA6 4_388_58
14 rows selected.
從上面顯示的內容可以看出,EMPLOYEE_ID=201的行記錄所對應的ROWID偽列值是“AAAM0YAAEAAAAGEAAD” ,使用DBMS_ROWID包對該偽列翻譯後的值是"4_388_3",這表示EMPLOYEE_ID為201的行記錄實際物理存儲地址位於4號文件第388個塊的第3行記錄。(注意數據塊裡行的記錄時從記錄號0開始算起的)。
上面的ROWID偽列的值可以直接在SQL語句的WHERE中使用如下:
SQL> select employee_id,first_name,rowid from emp_temp where rowid='AAAM0YAAEAAAAGEAAD';
EMPLOYEE_ID FIRST_NAME ROWID
----------- -------------------- ------------------
201 Michael AAAM0YAAEAAAAGEAAD
二,訪問索引的方法:
注意這裡所說的索引是指B數索引,ORACLE的其他索引暫時不考慮。
在ORACLE裡訪問B樹索引的操作都必須從根節點開始,即都會經歷一個從根節點到分支塊再到葉子塊的過程。索引葉子塊中包含被索引的鍵值和用於定位該索引鍵值所在的數據行在表中實際物理存儲位置的ROWID。B樹索引的結構決定了在ORACLE裡通過B樹索引訪問數據的過程是先訪問相關的B樹索引,然後根據訪問該索引後得到的ROWID再回表去訪問對應的數據行記錄(當然,如果目標SQL所要訪問的數據只通過訪問相關的索引就可以得到,那麼就不需要回表了)。
1,索引唯一性掃描(INDEX UNIQUE SCAN)是針對唯一性索引(UNIQUE INDEX)的掃描,它僅僅適用於WHERE條件裡是等值查詢的目標SQL。因為掃描的對象時唯一性索引,所以唯一性掃描的結果之多只返回一條記錄。
2,索引范圍掃描(INDEX RANGE SCAN)
3,索引全掃描(INDEX FULL SCAN)適用於所有類型的B樹索引,它是要掃描目標索引所有葉子塊的所有索引行。這裡需要注意的是,索引全掃描掃描目標索引的所有葉子塊,但並不意味著要掃描該索引的所有分支塊。索引全掃描執行的結果是有序的。默認情況下,索引全掃描的掃描結果的有序性決定了索引全掃描時不能夠並行執行的,並且通常情況下索引全掃描使用的是單塊讀。
4,索引快速全掃描(INDEX FAST FULL SCAN)
它和索引全掃描很相似,他們之間有以下三點區別:
a, 索引快速全掃描只適用於CBO。
b,索引快速全掃描可以使用多塊讀,也可以並行執行
c,索引快速全掃描的執行結果不一定是有序的。這是因為索引快速全掃描時,ORACLE是根據索引行在磁盤的物理存儲順序來掃描,而不是根據索引行的邏輯順序來掃描的,所以才不一定有序。
d, 索引跳躍式掃描(INDEX SKIP SCAN)
它使那些在WHERE條件中沒有對目標索引的前導列指定查詢條件但同時又對該索引的非前導列指定了查詢條件的目標SQL依然可以用上該索引。