教你如何成為Oracle 10g OCP - 第九章 物件管理(9) - 重建索引對效能的影響
9.2.5. 重建B樹索引對於查詢效能的影響
最後我們來看一下重建索引對於效能的提高到底會有什麼作用。假設
我們有一個表,該表具有1百萬條記錄,佔用了100000個資料塊。而在該表上
存在一個索引,在重建之前的pct_used為50%,高度為3,分支節點塊數為40個,
再加一個根節點塊,葉子節點數為10000個;重建該索引以後,pct_used為90%,
高度為3,分支節點塊數下降到20個,再加一個根節點塊,而葉子節點數下降
到5000個。
那麼從理論上說:
1)如果透過索引獲取單獨1條記錄來說:
重建之前的成本:1個根+1個分支+1個葉子+1個表塊=4個邏輯讀
重建之後的成本:1個根+1個分支+1個葉子+1個表塊=4個邏輯讀
效能提高百分比:0
2)如果透過索引獲取100條記錄(佔總記錄數的0.01%)來說,分兩種情況:
最差的clustering_factor(即該值等於表的資料行數):
重建之前的成本:1個根+1個分支+0.0001*10000(1個葉子)+100個表塊=103個邏輯讀
重建之後的成本:1個根+1個分支+0.0001*5000(1個葉子)+100個表塊=102.5個邏輯讀
效能提高百分比:0.5%(也就是減少了0.5個邏輯讀)
最好clustering_factor(即該值等於表的資料塊):
重建之前的成本:1個根+1個分支+0.0001*10000(1個葉子)+0.0001*100000(10個表塊)=13個邏輯讀
重建之後的成本:1個根+1個分支+0.0001*5000(1個葉子)+0.0001*100000(10個表塊)=12.5個邏輯讀
效能提高百分比:3.8%(也就是減少了0.5個邏輯讀)
3)如果透過索引獲取10000條記錄(佔總記錄數的1%)來說,分兩種情況:
最差的clustering_factor(即該值等於表的資料行數):
重建之前的成本:1個根+1個分支+0.01*10000(100個葉子)+10000個表塊=10102個邏輯讀
重建之後的成本:1個根+1個分支+0.01*5000(50個葉子)+10000個表塊=10052個邏輯讀
效能提高百分比:0.5%(也就是減少了50個邏輯讀)
最好clustering_factor(即該值等於表的資料塊):
重建之前的成本:1個根+1個分支+0.01*10000(100個葉子)+0.01*100000(1000個表塊)=1102個邏輯讀
重建之後的成本:1個根+1個分支+0.01*5000(50個葉子)+0.01*100000(1000個表塊)=1052個邏輯讀
效能提高百分比:4.5%(也就是減少了50個邏輯讀)
4)如果透過索引獲取100000條記錄(佔總記錄數的10%)來說,分兩種情況:
最差的clustering_factor(即該值等於表的資料行數):
重建之前的成本:1個根+1個分支+0.1*10000(1000個葉子)+100000個表塊=101002個邏輯讀
重建之後的成本:1個根+1個分支+0.1*5000(500個葉子)+100000個表塊=100502個邏輯讀
效能提高百分比:0.5%(也就是減少了500個邏輯讀)
最好clustering_factor(即該值等於表的資料塊):
重建之前的成本:1個根+1個分支+0.1*10000(1000個葉子)+0.1*100000(10000個表塊)=11002個邏輯讀
重建之後的成本:1個根+1個分支+0.1*5000(500個葉子)+0.1*100000(10000個表塊)=10502個邏輯讀
效能提高百分比:4.5%(也就是減少了500個邏輯讀)
5)對於快速全索引掃描來說,假設每次獲取8個資料塊:
重建之前的成本:(1個根+40個分支+10000個葉子)/ 8=1256個邏輯讀
重建之後的成本:(1個根+40個分支+5000個葉子)/ 8=631個邏輯讀
效能提高百分比:49.8%(也就是減少了625個邏輯讀)
從上面有關效能提高的理論描述可以看出,對於透過索引獲取的記錄
行數不大的情況下,索引碎片對於效能的影響非常小;當透過索引獲取較大
的記錄行數時,索引碎片的增加可能導致對於索引邏輯讀的增加,但是索引
讀與表讀的比例保持不變;同時,我們從中可以看到,clustering_factor對
於索引讀取的效能有很大的影響,並且對於索引碎片所帶來的影響具有很大的
作用;最後,看起來,索引碎片似乎對於快速全索引掃描具有最大的影響。
我們來看兩個實際的例子,分別是clustering_factor為最好和最差的
兩個例子。測試環境為8KB的資料塊,表空間採用ASSM的管理方式。先做一個
最好的clustering_factor的例子,建立測試表並填充1百萬條資料。
SQL> create table rebuild_test(id number,name varchar2(10));
SQL> begin
2 for i in 1..1000000 loop
3 insert into rebuild_test values(i,to_char(i));
4 if mod(i,10000)=0 then
5 commit;
6 end if;
7 end loop;
8 end;
9 /
該表具有1百萬條記錄,分佈在2328個資料塊中。同時由於我們的數
據都是按照順序遞增插入的,所以可以知道,在id列上建立的索引都是
具有最好的clustering_factor值的。我們執行以下查詢測試語句,分別
返回1、100、1000、10000、50000、100000以及1000000條記錄。
select * from rebuild_test where id = 10;
select * from rebuild_test where id between 100 and 199;
select * from rebuild_test where id between 1000 and 1999;
select * from rebuild_test where id between 10000 and 19999;
select /*+ index(rebuild_test) */ * from rebuild_test where id between 50000 and 99999;
select /*+ index(rebuild_test) */ * from rebuild_test where id between 100000 and 199999;
select /*+ index(rebuild_test) */ * from rebuild_test where id between 1 and 1000000;
select /*+ index_ffs(rebuild_test) */ id from rebuild_test where id between 1 and 1000000;
在執行這些測試語句前,先建立一個pctfree為50%的索引,來模擬索引碎
片,分析並記錄索引資訊。
SQL> create index idx_rebuild_test on rebuild_test(id) pctfree 50;
SQL> exec dbms_stats.gather_table_stats(user,'rebuild_test',cascade=>true);
然後執行測試語句,記錄每條查詢語句所需的時間;接下來以pctfree為10%
重建索引,來模擬修復索引碎片,分析並記錄索引資訊。
SQL> alter index idx_rebuild_test rebuild pctfree 10;
SQL> exec dbms_stats.gather_table_stats(user,'rebuild_test',cascade=>true);
接著再次執行這些測試語句,記錄每條查詢語句所需的時間。下表顯示了兩個索引資訊的對比情況。
pctfree
Height
blocks
br_blks
lf_blks
pct_used
clustering_factor
50%
3
4224
8
4096
49%
2326
10%
3
2304
5
2226
90%
2326
下表顯示了不同的索引下,執行測試語句所需的時間對比情況。
記錄數
佔記錄總數的百分比
pctused(50%)
pctused(90%)
效能提高百分比
1條記錄
0.0001%
0.01
0.01
0.00%
100條記錄
0.0100%
0.01
0.01
0.00%
1000條記錄
0.1000%
0.01
0.01
0.00%
10000條記錄
1.0000%
0.02
0.02
0.00%
50000條記錄
5.0000%
0.06
0.06
0.00%
100000條記錄
10.0000%
1.01
1.00
0.99%
1000000條記錄
100.0000%
13.05
11.01
15.63%
1000000條記錄(FFS)
100.0000%
7.05
7.02
0.43%
上面是對最好的clustering_factor所做的測試,那麼對於最差的
clustering_factor會怎麼樣呢?我們將rebuild_test中的id值反過來排
列,也就是說,比如對於id為3478的記錄,將id改為8743。這樣的話,
就將把原來按順序排列的id值徹底打亂,從而使得id上的索引的clustering_factor
變成最差的。為此,我寫了一個函式用來反轉id的值。
create or replace function get_reverse_value(id in number) return varchar2 is
ls_id varchar2(10);
ls_last_item varchar2(10);
ls_curr_item varchar2(10);
ls_zero varchar2(10);
li_len integer;
lb_stop boolean;
begin
ls_id := to_char(id);
li_len := length(ls_id);
ls_last_item := '';
ls_zero := '';
lb_stop := false;
while li_len>0 loop
ls_curr_item := substr(ls_id,li_len,1);
if ls_curr_item = '0' and lb_stop = false then
ls_zero := ls_zero || ls_curr_item;
else
lb_stop := true;
ls_last_item:=ls_last_item||ls_curr_item;
end if;
ls_id := substr(ls_id,1,li_len-1);
li_len := length(ls_id);
end loop;
return(ls_last_item||ls_zero);
end get_reverse_value;
接下來,我們建立我們第二個測試的測試表。並按照與第一個測
試案例相同的方式進行測試。注意,對於測試查詢來說,要把表名(包
括提示裡的)改為rebuild_test_cf。
SQL> create table rebuild_test_cf as select * from rebuild_test;
SQL> update rebuild_test_cf set name=get_reverse_value(id);
B-Tree索引結構參考:
http://www.cublog.cn/u3/112761/showart_2218897.html
http://space.itpub.net/?uid-9842-action-viewspace-itemid-324139
http://www.itpub.net/thread-300772-1-1.html
深入研究Oracle B樹索引系列 -by hanson
深入研究B樹索引(一):http://space.itpub.net/?uid-9842-action-viewspace-itemid-312607
深入研究B樹索引(二):http://space.itpub.net/?uid-9842-action-viewspace-itemid-321866
深入研究B樹索引(三、四)http://space.itpub.net/?uid-9842-action-viewspace-itemid-324139
深入研究B樹索引(四)續:http://space.itpub.net/?uid-9842-action-viewspace-itemid-324586
深入研究B樹索引(五):http://space.itpub.net/?uid-9842-action-viewspace-itemid-324587
深入研究B樹索引(五)續:http://space.itpub.net/?uid-9842-action-viewspace-itemid-324588
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/35489/viewspace-687457/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(8) - 如何重建B樹索引Oracle 10g物件索引
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(5) - 索引Oracle 10g物件索引
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(9) - 點陣圖(Bitmap)索引Oracle 10g物件索引
- 教你如何成為Oracle 10g OCP - 第九章 物件管理Oracle 10g物件
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(7) - B樹索引的對於DELETE的管理Oracle 10g物件索引delete
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(11) - 管理索引,sequence及resumableOracle 10g物件索引
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(2)Oracle 10g物件
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(3)Oracle 10g物件
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(4)Oracle 10g物件
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(10) - 點陣圖(Bitmap)索引Oracle 10g物件索引
- 教你如何成為Oracle 10g OCP - 第九章 物件管理(6) - B樹索引的訪問Oracle 10g物件索引
- 教你如何成為Oracle 10g OCP - 第十六章 ASM管理Oracle 10gASM
- 教你如何成為Oracle 10g OCP - 第六章 儲存管理Oracle 10g
- 教你如何成為Oracle 10g OCP - 第二十章 安全Oracle 10g
- 教你如何成為Oracle 10g OCP - 第七章 undo表空間管理Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十五章 自動化管理Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十四章 閃回Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十三章 RMAN管理的備份與恢復Oracle 10g
- 【刪除】教你如何成為Oracle 10g OCP - 第十五章 自動化管理Oracle 10g
- 教你如何成為Oracle 10g OCP - 第一章學習Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十二章 手工管理的備份與恢復Oracle 10g
- 【Oracle】-【COMMIT對索引的影響】-從trace看COMMIT對索引的影響OracleMIT索引
- 教你如何成為Oracle 10g OCP - 第十九章 資料遷移Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十一章 配置網路環境Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十三章補充:RMAN的組成及工作原理Oracle 10g
- 教你如何成為Oracle 10g OCP - 第五章 記憶體元件與Oracle程式Oracle 10g記憶體元件
- 教你如何成為Oracle 10g OCP - 第八章 使用者、許可權和角色管理Oracle 10g
- 【Oracle】-【ROWNUM與索引】-索引對ROWNUM檢索的影響Oracle索引
- 教你如何成為Oracle 10g OCP - 第三章 資料字典學習Oracle 10g
- 教你如何成為Oracle 10g OCP - 第八章 使用者、許可權和角色管理01Oracle 10g
- 教你如何成為Oracle 10g OCP - 第二十一章 全球化支援Oracle 10g
- 教你如何成為Oracle 10g OCP - 第二章學習 安裝及建庫Oracle 10g
- 教你如何在 elasticsearch 中重建索引Elasticsearch索引
- oracle點陣圖索引對DML操作的影響Oracle索引
- shrink 操作對索引的影響索引
- Update操作對索引的影響索引
- 第9 章、Oracle 10g 中的效能管理Oracle 10g
- 教你如何成為Oracle 10g OCP - 第十章 閂鎖、鎖定和併發性Oracle 10g