這篇是整理復習oracle關于訪問表數(shù)據(jù)的方法,在oracle數(shù)據(jù)庫中,要想訪問存儲在數(shù)據(jù)庫中的數(shù)據(jù),
成都創(chuàng)新互聯(lián)公司長期為上千多家客戶提供的網(wǎng)站建設服務,團隊從業(yè)經(jīng)驗10年,關注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務;打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為晉寧企業(yè)提供專業(yè)的成都做網(wǎng)站、成都網(wǎng)站制作、成都外貿網(wǎng)站建設,晉寧網(wǎng)站改版等技術服務。擁有十載豐富建站經(jīng)驗和眾多成功案例,為您定制開發(fā)。
要依次經(jīng)歷下面幾個步驟:
待執(zhí)行的SQL ----> 解析 ----> 優(yōu)化器處理 ----> 生成執(zhí)行計劃 ----> 實際執(zhí)行 ----> 返回執(zhí)行結果,
其中,在優(yōu)化器的處理這個階段,來決定訪問目標表數(shù)據(jù)的方式,即優(yōu)化器要采用什么方式去訪問具體
的數(shù)據(jù)。
在oracle中訪問表的方式分為兩種,一種是直接訪問表,一種是先訪問索引,再回表(當然,還有可能
只訪問索引就可以得到數(shù)據(jù),這樣的話,就不需要回表了)。
下面就分別整理出上述兩種訪問表中數(shù)據(jù)的方法。
1.訪問表的方法
直接訪問表中數(shù)據(jù)的方法有兩種: 全表掃描和ROWID掃描。
1.1 全表掃描
oracle在訪問目標表里面的數(shù)據(jù)時,會從該表所占用的第一個區(qū)(EXTENT)的第一個塊(BLOCK)開始掃
描,一直掃描到該表的高水位線(HWM,High Water Mark),最后返回滿足where條件的數(shù)據(jù)。
析:全表掃描時候會使用多塊讀,在目標表數(shù)據(jù)量不大的時候,效率是很高的,但問題在于,全表掃
描執(zhí)行時間不穩(wěn)定、不可控,執(zhí)行時間會隨著數(shù)據(jù)量遞增而遞增;
1.2 ROWID掃描
rowid掃描是指oracle在訪問數(shù)據(jù)時,是通過數(shù)據(jù)所在的物理存儲地址去定位并訪問數(shù)據(jù)。
對于oracle里的堆表來說,可通過oracle內置的rowid偽列得到對應行記錄所在的rowid的值。然后通過
DBMS_ROWID包里面的相關方法將rowid偽列翻譯成為對應數(shù)據(jù)行的實際物理存儲地址,如下
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數(shù)據(jù)庫中最常用的B樹索引,B樹索引類似一顆倒長的樹,包含兩種類型的數(shù)據(jù)塊,
一種是索引分支塊,一種是索引葉子塊。
B樹索引的優(yōu)勢有三點
a. 所有索引葉子塊層在同一層,它們距離索引根節(jié)點的深度相同,意思就是訪問索引葉子塊的任何
索引鍵值所花費的時間幾乎相同;
b. oracle會保證所有的B樹索引都是自平衡的,不可能出現(xiàn)不同的索引葉子塊不處于同一層的現(xiàn)象;
c. 通過B樹索引訪問表里記錄的效率并不會隨著相關表的數(shù)據(jù)量的遞增而明顯降低,也就是說通過
走索引訪問數(shù)據(jù)的時間是可控的、基本穩(wěn)定的,這也是走索引和全表掃描的最大區(qū)別;
下面是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。
默認情況下,索引全掃描要從左到右依次順序掃描目標索引所在葉子塊的所有索引行,由于索引是
有序的,所以索引全掃描的執(zhí)行結果也是有序的,并且是按照索引的索引鍵值列來排序,由此可見,
走索引全掃描在能夠達到排序的效果,同時避免了對該索引的索引鍵值列的真正排序操作,這個情況
可以在SQL時,在索引全掃描的執(zhí)行計劃中查看sorts(memory),sorts(disk)是否為0來確認。
索引全掃描的結果有序性,決定了索引全掃描不能并行執(zhí)行,并且通常情況下是單塊讀。
2.4索引快速全掃描
索引快速全掃描(INDEX FAST FULL SCAN)和索引全掃描類似,有如下幾個區(qū)別:
a. 只適用于CBO
b. 可以使用多塊讀,也可以并行執(zhí)行
c. 執(zhí)行結果不一定是有序的
2.5索引跳躍式掃描
索引跳躍式掃描(INDEX SKIP SCAN)適用于所有類型的復合B樹索引(包括唯一性索引和非
唯一性索引),跳躍的意思是,比如表DEMO1有字段(gender varchar2(1),id number not null),然
后給該表創(chuàng)建一個復合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;
/
然后,打開執(zhí)行計劃執(zhí)行一條查詢
set autotrace traceonly
select * from demo1 where id = 100;
在執(zhí)行計劃中可以看到用上了索引idx_xxx
而上面where條件是id=100,即它只對復合索引的第二列指定了查詢條件,并沒有對前導列
指定查詢條件,這就是索引跳躍掃描的情況。其實這個是oracle會對前導列的所有distinct值
做遍歷。
索引跳躍式掃描效率會隨著目標索引前導列的distinct值的遞增而效率遞減,所以它僅適用
于目標索引的前導列的distinct值數(shù)量較少、后續(xù)非前導列的可選擇性又非常好的情況下。
表的表數(shù)據(jù)的方法這塊到此整理完畢,后續(xù)有時間最好能每個點都舉例來整理。