Oracle索引分裂(Index Block Split)
Oracle索引分裂(Index Block Split)
索引分裂:index block split : 就是索引塊的分裂,當一次DML 事務操作修改了索引塊上的資料,但是舊有的索引塊沒有足夠的空間去容納新修改的資料,那麼將分裂出一個新的索引塊,舊有塊的部分資料放到新開闢的索引塊上去.
分裂的型別:根節點分裂,分支節點分裂,葉節點分裂(最頻繁發生,對效能影響最直接)
按照資料遷移量的比例,將索引分裂分為兩種型別:9-1分裂和5-5分裂.
9-1分裂:絕大部分資料還保留在舊有節點上,僅有非常少的一部分資料遷移到新節點上。
5-5分裂:舊節點和新節點上的資料比例幾乎是持平的。
5-5 分裂發生的條件:
1.左側節點發生新值插入時(新值小於索引中的最大值)。
2.發生DML 操作,索引塊上沒有足夠空間分配新的ITL槽。
3.新值待插入的索引上存在其他未提交的事務。
5-5分裂:
9-1分裂:通常是索引的鍵值是遞增的,表上的事務併發量比較低,可以保證新的資料塊上有較大的空閒空間插入新值。
5-5分裂:表上的事務併發度較高,操作的資料是無序的,需保證分裂的新舊資料塊上有相對較大的空閒空間容納新事務的操作。
9-1分裂如下:
對效能來說,無論9-1還是5-5 都不是什麼好事。
索引結構如下:
--9-1 分裂分析
create table t_index(id number,name varchar2(100));
create index i_index_01 on t_index(id);
alter session set events '10224 trace name context forever,level 1';
declare
begin
for i in 1 .. 3000 loop
insert into t_index values (i, 'ls');
end loop;
commit;
end;
alter session set events '10224 trace name context off';
splitting leaf,dba 0x02015f04,time 15:19:09.639
kdisnew_bseg_srch_cbk reject block -mark full,dba 0x02015f04,time 15:19:09.640
kdisnew_bseg_srch_cbk rejecting block ,dba 0x02015f04,time 15:19:09.640
kdisnew_bseg_srch_cbk using block,dba 0x02015f1e,time 15:19:09.640
kdisnew_bseg_srch_cbk reject block -mark full,dba 0x02015f1e,time 15:19:09.640
kdisnew_bseg_srch_cbk rejecting block ,dba 0x02015f1e,time 15:19:09.640
kdisnew_bseg_srch_cbk using block,dba 0x02015f22,time 15:19:09.640
splitting leaf,dba 0x02015f22,time 15:19:09.676
kdisnew_bseg_srch_cbk reject block -mark full,dba 0x02015f22,time 15:19:09.676
kdisnew_bseg_srch_cbk rejecting block ,dba 0x02015f22,time 15:19:09.676
kdisnew_bseg_srch_cbk using block,dba 0x02015f26,time 15:19:09.676
splitting leaf,dba 0x02015f26,time 15:19:09.711
kdisnew_bseg_srch_cbk reject block -mark full,dba 0x02015f26,time 15:19:09.711
kdisnew_bseg_srch_cbk rejecting block ,dba 0x02015f26,time 15:19:09.711
kdisnew_bseg_srch_cbk using block,dba 0x02015f2a,time 15:19:09.711
splitting leaf,dba 0x02015f2a,time 15:19:09.748
kdisnew_bseg_srch_cbk reject block -mark full,dba 0x02015f2a,time 15:19:09.748
kdisnew_bseg_srch_cbk rejecting block ,dba 0x02015f2a,time 15:19:09.748
kdisnew_bseg_srch_cbk using block,dba 0x02015f2e,time 15:19:09.748
splitting leaf,dba 0x02015f2e,time 15:19:09.784
kdisnew_bseg_srch_cbk reject block -mark full,dba 0x02015f2e,time 15:19:09.784
kdisnew_bseg_srch_cbk rejecting block ,dba 0x02015f2e,time 15:19:09.784
kdisnew_bseg_srch_cbk using block,dba 0x02015f32,time 15:19:09.784
--驗證是否發生了9-1分裂:
SQL> select s.SID, n.NAME, s.VALUE
2 from v$sesstat s, v$statname n
3 where s.STATISTIC# = n.STATISTIC#
4 and sid in (select sid from v$mystat)
5 and value > 0
6 and n.NAME like '%split%'
7 ;
SID NAME VALUE
---------- ---------------------------------------------------------------- ----------
776 leaf node splits 5
776 leaf node 90-10 splits 5
記錄了5次索引葉子節點資料塊的分裂,也就是說整個過程發生了5次索引分裂,因為表和索引都是新建的,所以次索引樹結構應該有6個葉節點資料塊。
SQL> ALTER SESSION SET EVENTS 'immediate trace name treedump level 159572';
Session altered.
*** 2015-12-22 16:19:30.295
branch: 0x2015f04 33644292 (0: nrow: 6, level: 1)
leaf: 0x2015f1e 33644318 (-1: nrow: 540 rrow: 540)
leaf: 0x2015f22 33644322 (0: nrow: 533 rrow: 533)
leaf: 0x2015f26 33644326 (1: nrow: 533 rrow: 533)
leaf: 0x2015f2a 33644330 (2: nrow: 533 rrow: 533)
leaf: 0x2015f2e 33644334 (3: nrow: 533 rrow: 533)
leaf: 0x2015f32 33644338 (4: nrow: 328 rrow: 328)
----- end tree dump
ANALYZE INDEX I_INDEX_01 VALIDATE STRUCTURE;
SQL> SELECT HEIGHT,
2 ROUND((DEL_LF_ROWS_LEN / LF_ROWS_LEN) * 100, 2) || '%' RATIO,
3 PCT_USED
4 FROM INDEX_STATS
5 WHERE NAME = 'I_INDEX_01';
HEIGHT RATIO PCT_USED
---------- ----------------------------------------- ----------
2 0% 81
SQL> SELECT PCT_FREE FROM USER_INDEXES WHERE INDEX_NAME = 'I_INDEX_01';
PCT_FREE
----------
10
--分析i_index_01 結構: 索引空間,使用率大約81% 左右,從dump檔案看出,每個葉子塊大約儲存530 個條目,
簡單的換算:81% 充盈的葉塊可以儲存 533 行記錄,那麼一個100% 充盈的塊就可以儲存 533/0.81 =658行記錄
同時我們看到索引的PCT_FREE=10%,也就是說索引的葉塊的利用率可達到90% ,單塊可以儲存記錄行數為658 * 0.9=592
但是實際情況是單塊儲存記錄的行數還沒到達592(才530)就開始分裂了。PCT_FREE 引數的設定被忽略了。
--5-5分裂分析:
create table t_index_1(id number,name varchar2(100));
create index i_index_02 on t_index_1(id);
alter session set events '10224 trace name context forever,level 1';
--反序插入3000條記錄
declare
begin
for i in 1 .. 3000 loop
insert into t_index_1 values (3001-i, 'ls');
end loop;
commit;
end;
--5-5分裂會導致索引葉子節點的資料塊使用率不高--(使用率不高的時候就發生了分裂)
SQL> select s.SID, n.NAME, s.VALUE
from v$sesstat s, v$statname n
where s.STATISTIC# = n.STATISTIC#
and sid in (select sid from v$mystat)
and value > 0
and n.NAME like '%split%';
SID NAME VALUE
---------- ---------------------------------------------------------------- ----------
776 leaf node splits 10
ANALYZE INDEX I_INDEX_02 VALIDATE STRUCTURE;
SQL> SELECT HEIGHT,
2 ROUND((DEL_LF_ROWS_LEN / LF_ROWS_LEN) * 100, 2) || '%' RATIO,
3 PCT_USED
4 FROM INDEX_STATS
5 WHERE NAME = 'I_INDEX_02';
HEIGHT RATIO PCT_USED
---------- ----------------------------------------- ----------
2 0% 47
--此時索引空間總體的使用率由之前的81% 下降到47%
select object_id, object_name
from dba_objects
where owner = user
and object_name = 'I_INDEX_01'
--
alter session set events 'immediate trace name treedump level 88317'
*** 2015-12-24 13:31:00.102
*** SESSION ID:(776.93) 2015-12-24 13:31:00.102
*** CLIENT ID:() 2015-12-24 13:31:00.102
*** SERVICE NAME:(SYS$USERS) 2015-12-24 13:31:00.102
*** MODULE NAME:(SQL*Plus) 2015-12-24 13:31:00.102
*** ACTION NAME:() 2015-12-24 13:31:00.102
----- begin tree dump
branch: 0x2016004 33644548 (0: nrow: 11, level: 1)
leaf: 0x201601e 33644574 (-1: nrow: 375 rrow: 375)
leaf: 0x201600b 33644555 (0: nrow: 262 rrow: 262)
leaf: 0x2016007 33644551 (1: nrow: 262 rrow: 262)
leaf: 0x201603e 33644606 (2: nrow: 267 rrow: 267)
leaf: 0x201603a 33644602 (3: nrow: 262 rrow: 262)
leaf: 0x2016036 33644598 (4: nrow: 262 rrow: 262)
leaf: 0x2016032 33644594 (5: nrow: 262 rrow: 262)
leaf: 0x201602e 33644590 (6: nrow: 262 rrow: 262)
leaf: 0x201602a 33644586 (7: nrow: 262 rrow: 262)
leaf: 0x2016026 33644582 (8: nrow: 262 rrow: 262)
leaf: 0x2016022 33644578 (9: nrow: 262 rrow: 262)
----- end tree dump
--單塊儲存的記錄行數由570行下降到262行。說明此時索引有點"虛胖"
導致問題:在一次簡單的查詢或者dml操作中,會掃描非常多的索引塊,直接導致I/O次數的增加,特別是在併發度很高的表上。
5-5分裂中,PCT_FREE引數再一次被忽視。引數PCT_FREE在索引建立時起作用,而在使用時往往被忽略。
SQL> SELECT PCT_FREE FROM USER_INDEXES WHERE INDEX_NAME = 'I_INDEX_02';
PCT_FREE
----------
10
--在索引塊上,以下兩種情況會觸發'enq: TX-allocate ITL entry' 等待:
1.達到資料塊上最大事務數限制
2.遞迴事務ITL 爭用
總結:
索引的爭用源自於索引的分裂,而觸發索引的分裂的契機就是索引上的高併發事務操作。
如何去解決高併發導致索引分裂的爭用:
1.增加ITL槽來增加併發處理能力-->修改索引initrans 引數
其實修改initrans 引數並沒有真正解決問題,隨著併發度的不斷提升,ITL 槽的爭用也越發激烈。
2.反向建索引。利:入庫高效了,幾乎完全消除了enq:TX-index contention 弊:資料讀取低效,本來訪問一個索引塊即可,現在需要訪問多個索引塊了。增加了額外I/O開銷。
About Me
...............................................................................................................................
● 本文整理自網路
● 本文在itpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新
● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/
● 本文部落格園地址:http://www.cnblogs.com/lhrbest
● 本文pdf版及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/
● 資料庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/
● QQ群:230161599 微信群:私聊
● 聯絡我請加QQ好友(646634621),註明新增緣由
● 於 2017-05-09 09:00 ~ 2017-05-30 22:00 在魔都完成
● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解
● 版權所有,歡迎分享本文,轉載請保留出處
...............................................................................................................................
拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26736162/viewspace-2139232/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle index索引塊分裂split資訊彙總OracleIndex索引
- zt_如何確定index root block split索引塊分裂的時間點IndexBloC索引
- Oracle索引塊分裂split資訊彙總Oracle索引
- index block split相關一些知識IndexBloC
- 索引分裂造成的index contention等待事件的診斷索引Index事件
- oracle index索引原理OracleIndex索引
- 索引分裂的enq索引ENQ
- Oracle筆記 之 索引(index)Oracle筆記索引Index
- oracle index索引結構(一)OracleIndex索引
- oracle dml與索引index(一)Oracle索引Index
- 【ASK_ORACLE】關於Oracle索引分裂你需要知道的Oracle索引
- ORACLE 12c索引分裂引起的會話夯Oracle索引會話
- oracle 點陣圖索引(bitmap index)Oracle索引Index
- oracle index索引相關筆記OracleIndex索引筆記
- RMAN處理split block問題BloC
- oracle全文索引之STOPLIST_ CTXCAT 索引_INDEX SETOracle索引Index
- index索引Index索引
- 【INDEX】Oracle 索引常見知識梳理IndexOracle索引
- Oracle Index Key Compression索引壓縮OracleIndex索引
- index leaf block索引葉子塊何時會刪除—part1IndexBloC索引
- 資料庫索引分裂 問題分析資料庫索引
- Oracle中的虛擬列索引-nosegment indexOracle索引Index
- 【INDEX】Oracle分割槽索引技術詳解IndexOracle索引
- 介紹Oracle Virtual Index虛擬索引(上)OracleIndex索引
- index branch and leaf block structure(轉)IndexBloCStruct
- 理解index leaf node 90-10 splitIndex
- 分割槽索引之本地(local index)索引和全域性索引(global index)索引Index
- Elasticsearch之索引模板index template與索引別名index aliasElasticsearch索引Index
- Mysql——index(索引)使用MySqlIndex索引
- mysql 索引( mysql index )MySql索引Index
- 【INDEX】Oracle19c 自動索引技術初探IndexOracle索引
- index_oracle索引梳理系列及分割槽表梳理IndexOracle索引
- Oracle 反向索引 where index_column like '%xxx'Oracle索引Index
- oracle分割槽partition及分割槽索引partition index(一)Oracle索引Index
- 【oracle 效能優化】組合索引之index_ssOracle優化索引Index
- oracle全文索引之About_INDEX_THEMES操作Oracle索引Index
- 點陣圖索引(Bitmap Index)——索引共用索引Index
- 【INDEX】Postgresql索引介紹IndexSQL索引