Oracle索引樹的結構

關於Oracle索引樹的結構以及它們對Oracle性能調優是否重要存在大量的、激烈的爭論,而且已經有很多文章試圖來描述這些重要的Oracle性能工具的內部工作機制。關於這個論題也出現了一些新書,例如由“國際Oracle用戶組”(IOUG)主席Kim Floss所著的《Oracle索引管理祕訣》和《Oracle SQL 性能調優和“基於代價的優化器”內幕》。
正如我們知道的,Oracle提供了大量索引結構,每種索引結構都有其好處和不足:
* B樹索引。從最早的Oracle發行版本開始,Oracle就一直使用的標準樹索引就是B樹索引。
* 位圖索引。當某個索引列含有很少數量的不同的值(即低基數)時,使用位圖索引。這對於那些只讀數據庫而言速度超快,但對需要經常性更新的系統不適合。
* 位圖連接索引。這是針對來自其他表的數據列出現在某個連接表的多列索引時使用的索引。下面是在from子句和where子句中使用類似SQL的創建索引的惟一語法。
create bitmap index
part_suppliers_state
on
inventory( parts.part_type, supplier.state )
from
inventory i,
parts p,
supplier s
where
i.part_id=p.part_id
and
i.supplier_id=p.supplier_id;
儘管有關索引重建的爭論仍在激烈進行着,但還是存在每個人都認可的索引管理的某些領域。在內部機制上,一個Oracle B-樹索引的結構和一個UNIX I-結點的結構非常相似。索引中的每個數據塊都是索引樹中的一個結點,位於最底部的結點(葉數據塊)包含一對符號鍵和行ID值。
Oracle b-樹索引
爲了正確管理這些數據塊,Oracle控制着每個數據塊中指針的分配。隨着一棵Oracle樹的增長(通過往表裏插入新行),Oracle會填充這個數據塊,當這個數據塊滿時Oracle會分裂它,創建新的索引結點(數據塊)來管理索引內的符號鍵。
因此,一個Oracle索引塊可能包含以下兩種類型的指針:
* 指向其他索引結點(數據塊)的指針
* 指向數據庫表中特定行的行ID指針
Oracle管理着索引塊內指針的分配,這就是爲什麼我們不能爲索引指定一個PCTUSED值(自由列表重鏈接門檻)的原因。當我們檢查一個索引塊的結構時,我們發現每個索引結點內部條目的數量是下面兩個值的一個函數:
1. 符號鍵的長度
2. 索引表空間的塊尺寸
由於塊尺寸影響每個索引結點內部的符號鍵的數量,可以推理出:塊尺寸對一棵索引樹的結構也會有影響。在其他條件相同的情況下,採用32K的大數據塊能容納更多的符號鍵,從而能夠比在2K表空間中創建的相同的索引更加平整。採用大的數據塊也將減少索引訪問期間一致獲取的數量,從而提高分散讀訪問的性能。
索引中的每個數據塊包含索引樹中的“結點”,位於最底部的結點(葉數據塊)包含一對符號鍵和行ID值。隨着一棵Oracle樹的增長(通過往表裏插入新行),Oracle會填充這個數據塊,當這個數據塊滿時Oracle會分裂它,創建新的索引結點(數據塊)來管理索引內的符號鍵。因此,一個Oracle索引塊可能包含指向其他索引結點或行ID/符號鍵對的指針。
索引行爲和Oracle塊尺寸
由於塊尺寸影響每個索引結點內部的符號鍵的數量,可以推理出:塊尺寸對一棵索引樹的結構也會有影響。在其他條件相同的情況下,採用32K的大數據塊能容納更多的符號鍵,從而能夠比在2K表空間中創建的相同的索引更加平整。
今天,大多數Oracle性能調優專家都利用Oracle提供的多種塊尺寸的特色,因爲它提供了緩衝區隔離和以最合適塊尺寸來存放對象從而減少緩衝區浪費的能力。一些Oracle基準測試的世界記錄都使用很大的數據緩衝區和多種塊尺寸。
根據《Oracle數據庫管理員認證:“Oracle 認證數據庫管理專家”教師指南》一書的作者Christopher Foot的一篇文章,更大的塊尺寸在某些情況下非常有幫助:
“更大的塊尺寸意味着在B-樹索引的分支結點中有更多的空間來存儲符號鍵,從而可以降低樹的高度和提高索引查詢的性能。”
在任何情況下,似乎有證據表明塊尺寸影響樹的結構,這爲數據塊影響樹的結構提供了有力支持。
你可以使用大數據塊(16-32)緩衝區來存儲來自作爲重複性大規模掃描對象的索引或表中的數據。這真的會提高性能麼?一個小的但透漏內情的測試能回答這個問題。
在這個測試中,將對某個使用8K數據塊尺寸的Oracle 9i數據庫執行以下查詢,這個數據庫同時也使用16K緩衝區和16K大小的表空間。
select
count(*)
from
eradmin.admission
where
patient_id between 1 and 40000;
表eradmin.admission含有150,000行數據,並在patient_id列上建立了一個索引。對上面的查詢語句執行EXPLAIN命令揭示出:它使用索引範圍掃描來產生想要的目的結果:
Execution Plan
----------------------------------------------------------
SELECT STATEMENT Optimizer=CHOOSE
(Cost=41 Card=1 Bytes=4)
1 0 SORT (AGGREGATE)
2 1 INDEX (FAST FULL SCAN) OF 'ADMISSION_PATIENT_ID'
(NON-UNIQUE) (Cost=41 Card=120002 Bytes=480008)

使用位於一個標準8K表空間的索引來執行這個查詢(兩次以消除分析活動並緩衝任何數據)產生了以下實時統計信息:
Statistics
---------------------------------------------------
0 recursive calls
0 db block gets
421 consistent gets
0 physical reads
0 redo size
371 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
爲了測試新的16K緩衝區和16K表空間的效果,將使用16K的表空間來重建這個查詢所用的索引,16K的表空間和原來的8K的表空間相比,除了更大的塊尺寸其他特性一模一樣。
alter index
eradmin.admission_patient_id
rebuild nologging noreverse tablespace indx_16k;
一旦在16K表空間中建立好這個索引,就再次執行這個查詢(同樣也是執行兩次),會產生以下的運行時統計信息:
Statistics
---------------------------------------------------
0 recursive calls
0 db block gets
211 consistent gets
0 physical reads
0 redo size
371 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
正如你所看到的,邏輯讀操作的次數被減少了一半,僅僅是由於使用了新的16K表空間和16K數據緩衝區。很顯然,正確使用新的數據緩衝區和Oracle9i及其以上版本的多種塊尺寸表空間的特色,很值得在你的數據庫中被試驗和研究。
定期進行索引重建?
爭論的另外一個領域是:是否存在一些確定的規則可以用來確定何時能夠從索引重建中獲取性能提高。許多使用Oracle的企業都定期進行索引重建,並聲稱在他們和重建他們的Oracle B-樹索引後獲得了相當大的速度提升。
在“Oracle世界2003”上,展示了Sushil Kumar所著的一篇題爲“Oracle數據庫10g:自我管理的數據庫”的文章,Kumar聲明說Oracle10g的“自動維護任務”(AMT)特色將自動檢測並重建潛在的最優化的索引。
“自動工作負載信息庫(AWR)給oracle10g提供了關於數據庫各種使用情況的詳細信息。通過分析存儲在自動工作負載信息庫(AWR)中的信息,10g數據庫可以決定是否需要執行數據庫性能維護任務,比如優化器統計數字的刷新、重建索引等等。 以“自動維護任務”AMT爲基礎,oracle數據庫可以自動執行這些操作。”
儘管如此,仍有不少反對定期重建索引的論點。一些oracle內部的專家堅持認爲oracle索引在空間重用和訪問速度上是非常高效的,b-樹索引在極少情況下才需要被重建。他們堅持認爲邏輯輸入輸出的減少應該是可測量的,並且如果重建索引是有好處的,某些人應該已經提出了可以證明的規則。
結論
多種數據塊尺寸的特色能夠提高Oracle索引的性能,而且在某些情況下重建索引可以提高查詢速度,這是顯而易見的。人們期望新的Oracle10g“自動維護任務”AMT允許自動檢測並重建潛在的最優化索引結構。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章