ORACLE訪問數據的方法
這篇是整理復習oracle關於訪問表數據的方法,在oracle數據庫中,要想訪問存儲在數據庫中的數據,
要依次經歷下面幾個步驟:
待執行的SQL ----> 解析 ----> 優化器處理 ----> 生成執行計劃 ----> 實際執行 ----> 返回執行結果,
其中,在優化器的處理這個階段,來決定訪問目標表數據的方式,即優化器要采用什麽方式去訪問具體
的數據。
在oracle中訪問表的方式分為兩種,一種是直接訪問表,一種是先訪問索引,再回表(當然,還有可能
只訪問索引就可以得到數據,這樣的話,就不需要回表了)。
下面就分別整理出上述兩種訪問表中數據的方法。
1.訪問表的方法
直接訪問表中數據的方法有兩種: 全表掃描和ROWID掃描。
1.1 全表掃描
oracle在訪問目標表裏面的數據時,會從該表所占用的第一個區(EXTENT)的第一個塊(BLOCK)開始掃
描,一直掃描到該表的高水位線(HWM,High Water Mark),最後返回滿足where條件的數據。
析:全表掃描時候會使用多塊讀,在目標表數據量不大的時候,效率是很高的,但問題在於,全表掃
描執行時間不穩定、不可控,執行時間會隨著數據量遞增而遞增;
1.2 ROWID掃描
rowid掃描是指oracle在訪問數據時,是通過數據所在的物理存儲地址去定位並訪問數據。
對於oracle裏的堆表來說,可通過oracle內置的rowid偽列得到對應行記錄所在的rowid的值。然後通過
DBMS_ROWID包裏面的相關方法將rowid偽列翻譯成為對應數據行的實際物理存儲地址,如下
select empno,ename,rowid,dbms_rowid.rowid_relative_fno(rowid)||'_'||
dbms_rowid.rowid_block_number(rowid)||'_'||dbms_rowid.rowid_row_number(rowid)
from emp;
2.訪問索引的方法
這裏說的是oracle數據庫中最常用的B樹索引,B樹索引類似一顆倒長的樹,包含兩種類型的數據塊,
一種是索引分支塊,一種是索引葉子塊。
B樹索引的優勢有三點
a. 所有索引葉子塊層在同一層,它們距離索引根節點的深度相同,意思就是訪問索引葉子塊的任何
索引鍵值所花費的時間幾乎相同;
b. oracle會保證所有的B樹索引都是自平衡的,不可能出現不同的索引葉子塊不處於同一層的現象;
c. 通過B樹索引訪問表裏記錄的效率並不會隨著相關表的數據量的遞增而明顯降低,也就是說通過
走索引訪問數據的時間是可控的、基本穩定的,這也是走索引和全表掃描的最大區別;
下面是oracle裏面的常見的訪問B樹索引的方法介紹
2.1 索引唯一性掃描
索引唯一性掃描(INDEX UNIQUE SCAN)是針對唯一性索引(UNIQUE INDEX)的掃描,不過呢它僅
僅適用於where條件裏等值查詢類SQL,由於掃描對象是唯一性索引,所以掃描結果至多返回一條記
錄。
2.2 索引範圍掃描
索引範圍掃描(INDEX RANGE SCAN)適用於所有類型的B樹索引,當掃描對象是唯一性索引時,目
標SQL的where條件一定是範圍查詢(謂詞條件為BETWEEN、<、>等);當掃描對象是非唯一性索引
時候,對目標SQL的where條件沒有限制(可以是等值查詢,也可以是範圍查詢)。
2.3 索引全掃描
索引全掃描(INDEX FULL SCAN)適用於所有類型的B樹索引,指的是要掃描目標索引所有必要分支
塊下的葉子塊的所有索引行。默認情況下,oracle在做索引全掃描時候只需要通過訪問定位到位於該
索引最左邊的葉子塊的第一行索引行,然後利用該索引葉子塊之間的雙向指針鏈表,從左到右依次順
序掃描該索引所有葉子塊的所有索引行。
索引全掃描的前提條件是,目標索引至少有一個索引鍵值列的屬性是NOT NULL。
默認情況下,索引全掃描要從左到右依次順序掃描目標索引所在葉子塊的所有索引行,由於索引是
有序的,所以索引全掃描的執行結果也是有序的,並且是按照索引的索引鍵值列來排序,由此可見,
走索引全掃描在能夠達到排序的效果,同時避免了對該索引的索引鍵值列的真正排序操作,這個情況
可以在SQL時,在索引全掃描的執行計劃中查看sorts(memory),sorts(disk)是否為0來確認。
索引全掃描的結果有序性,決定了索引全掃描不能並行執行,並且通常情況下是單塊讀。
2.4索引快速全掃描
索引快速全掃描(INDEX FAST FULL SCAN)和索引全掃描類似,有如下幾個區別:
a. 只適用於CBO
b. 可以使用多塊讀,也可以並行執行
c. 執行結果不一定是有序的
2.5索引跳躍式掃描
索引跳躍式掃描(INDEX SKIP SCAN)適用於所有類型的復合B樹索引(包括唯一性索引和非
唯一性索引),跳躍的意思是,比如表DEMO1有字段(gender varchar2(1),id number not null),然
後給該表創建一個復合B樹索引如下
create index idx_xxx on demo1(gender,id);
然後給表以下面形式插入多行記錄
begin
for i in 1..5000 loop
insert into demo1 values('F',i);
end loop
commit;
end;
/
begin
for i in 5001..10000 loop
insert into demo1 values('M',i);
end loop
commit;
end;
/
然後,打開執行計劃執行一條查詢
set autotrace traceonly
select * from demo1 where id = 100;
在執行計劃中可以看到用上了索引idx_xxx
而上面where條件是id=100,即它只對復合索引的第二列指定了查詢條件,並沒有對前導列
指定查詢條件,這就是索引跳躍掃描的情況。其實這個是oracle會對前導列的所有distinct值
做遍歷。
索引跳躍式掃描效率會隨著目標索引前導列的distinct值的遞增而效率遞減,所以它僅適用
於目標索引的前導列的distinct值數量較少、後續非前導列的可選擇性又非常好的情況下。
表的表數據的方法這塊到此整理完畢,後續有時間最好能每個點都舉例來整理。
ORACLE訪問數據的方法