標籤:database oracle 效能 資料庫
上篇文章講述了全掃描,這篇文章將介紹索引的結構和掃描方式,在後面將開始講述每一種掃描方式。
當Oracle通過索引檢索具體的一列或多列的列值時,就會執行索引掃描。首先我們來看看索引節點包含的資料。
索引節點包含的資料
索引可以被建立在表的單列或者多列上,索引中包含了這些列的值、rowid和一些其它資訊,我們關心的只有列值和rowid。由於索引帶有列值,應此如果你的SQL語句只涉及到索引的列,那麼Oracle就只從索引本身檢索列值,而不需要訪問表。如果查詢涉及到索引列以外的列,Oracle就需要使用rowid來訪問表。
下面是一個rowid的例子:
AAAN0+AABAAAPIqABj
rowid中包含了檔案編號、資料區塊編號和行號,通過下面的SQL我們可以將rowid分解為可讀的具體的資訊,使用先前建立的表T2:
select t.rowid, (select file_name from dba_data_files where file_id = dbms_rowid.rowid_to_absolute_fno(t.rowid, user, 'T2')) file_name, dbms_rowid.rowid_block_number(t.rowid) bokc_no, dbms_rowid.rowid_row_number(t.rowid) row_no from t2 t
執行後得到結果:
ROWIDFILE_NAMEBOKC_NOROW_NOAAAN0+AABAAAPIqAAAE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619940AAAN0+AABAAAPIqAABE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619941AAAN0+AABAAAPIqAACE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619942......AAAN0+AABAAAPIqAJdE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994605AAAN0+AABAAAPIqAJeE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994606AAAN0+AABAAAPIqAJfE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994607AAAN0+AABAAAPIqAJgE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994608AAAN0+AABAAAPIqAJhE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994609AAAN0+AABAAAPIqAJiE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994610AAAN0+AABAAAPIqAJjE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61994611AAAN0+AABAAAPIrAAAE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619950AAAN0+AABAAAPIrAABE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619951AAAN0+AABAAAPIrAACE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619952AAAN0+AABAAAPIrAADE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619953AAAN0+AABAAAPIrAAEE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619954......AAAN0+AABAAAPIrAJVE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61995597AAAN0+AABAAAPIrAJWE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61995598AAAN0+AABAAAPIrAJXE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61995599AAAN0+AABAAAPIrAJYE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61995600AAAN0+AABAAAPIrAJZE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61995601AAAN0+AABAAAPIrAJaE:\ORACLE\ORADATA\LY\SYSTEM01.DBF61995602AAAN0+AABAAAPIsAAAE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619960AAAN0+AABAAAPIsAABE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619961AAAN0+AABAAAPIsAACE:\ORACLE\ORADATA\LY\SYSTEM01.DBF619962......
這裡將得到表T2中所有行的具體位置,包括所在的檔案、資料區塊號和塊內的行號。我們可以看到資料的分布情況。
需要注意的是dbms_rowid.rowid_to_absolute_fno函數,定義如下:
function dbms_rowid.rowid_to_absolute_fno(rowid in rowid,schema_name in varchar2,object_name in varchar2)return number
1)rowid:rowid;
2)schema_name:使用者名稱,這裡是目前使用者(user)
3)object_name:對象名,這裡是T2
那麼,通過上面的描述我們就可以得到通過索引掃描尋找資料的步驟:
1)得到索引的資料區塊,得到索引列和rowid;
2)如果查詢只涉及到索引列,則查詢結束;
3)否則通過rowid找到資料區塊,並通過行號定位到資料。
索引結構和索引掃描類型介紹
在這裡只討論B-樹索引,B-樹索引是一個樹狀結構。表剛建立時是一個空白,對應的索引將只存在一個根節點,索引高度是1,另外索引還有一個blevel的統計資訊用來表示一個索引中的分支層級數,該值為0,通過下面的查詢可以得到:
select index_name,blevel from user_indexes where index_name =upper( 'index_name');
隨著新的資料插入到表中,新的索引條目將被增加到塊中,直到塊滿,這時,Oracle將會分配兩個新的索引塊並將索引條目加入這兩個新的葉子塊中,先前的索引塊將變為指向新索引塊的指標,這個指標包含指向新索引塊的相對資料區塊地址(Relative Block Address,RBA)和相關葉子塊中最低索引值。到這時,索引的高度將變為2,blevel值將變為1。
隨著表中資料的繼續增長,索引塊會進一步分裂,高度會繼續增長,最終形成一個樹狀結構:
瞭解了索引的結構,很容易就能理解索引掃描,索引掃描有很多種不同的類型,但都必須遍曆索引結構以搜尋到匹配的葉子節點。首先通過一次單塊讀來擷取索引的根塊,然後通過多次的單塊讀來擷取路徑節點的塊,直到葉子節點所在的塊(匹配的塊),從匹配的葉子節點中擷取資料的rowid,在通過rowid使用單塊讀擷取一行資料,因此,如果索引結構的高度為4,則查詢一行資料需要讀取5個塊,4個索引塊和1個表資料區塊。
索引掃描類型包括:索引範圍掃描、索引唯一掃描、索引全掃描、索引跳躍掃描和索引快速全掃描。在後面將詳細講述每一種掃描方式的特點和應用範圍。
Oracle效能分析5:資料訪問方式之索引結構和掃描方式介紹