原文轉自http://www.itpub.net/thread-1713308-1-1.html
訪問頻率非常高的數據塊被稱爲熱塊(Hot Black),當很多用戶同時訪問某個數據塊時,就會導致Lanch爭用。常見的Lanch爭用
A buffer busy waits
B cachebuffer chain
一、如果是cachebuffer chain Latch的,要看訪問相同數據塊的會話會太長或這個列表太長
1)如果這個列表太長
原因:
如果一條hash chain比其他hash chain長,它所管理的buffer header更多,那麼發生cache buffers chains latch等待的機率就更大,
辦法:
針對這個問題,可以通過增加hash bucket的數量進而影響hash chain的數量來達到縮短hash chain的目的.參數_db_block_hash_latches
原理:
8.0之前,hash buckets的個數等於db block buffers/4。也就是說,平均一個hash bucket上掛4個block。當然這只是平均值,很有可能通過hash函數轉換block header的地址後會導致一個bucket上掛很多個block。
8.0以後,oracle改成了hashbuckets=2*db block buffers。主要是爲了降低一個bucket上掛的block的個數,從而減少掃描bucket所花費的時間。所以說,平均是一個bucket上掛0.5個block。但是實際上,一個bucket上可能會掛較多的block,而有些bucket上則沒有掛block,這由block的地址決定。所以,增加bucket的個數,就可以增加block平均分佈在bucket上的概率。
注:
其實在Oracle9i之後,我們基本上不會遇到這個問題了,除非遇到Bug。所以這個是不推薦的,記住,在對Oracle的隱含參數做修改之前一定要諮詢Oracle Support。
2)訪問相同數據塊的會話會太長
原因:
當多個會話重複訪問一個或多個由同一個子chche buffer chains鎖存器保護的塊時,熱塊就產生。
辦法:
調整隱藏參數_spin_count,增加進程成功獲取latch的可能性,這個方法要慎用,增大_spin_count會增加cpu的負荷從而可能造成負面效果。
二、如果是buffer busy waits
1、、找到熱塊產生的SQL,根據執行計劃查看是否合理,改變SQL爲最優SQL
A、找到最熱的數據塊的latch和buffer信息
select b.addr,a.ts#,a.dbarfil,a.dbablk,a.tch,b.gets,b.misses,b.sleeps from
(select * from (select addr,ts#,file#,dbarfil,dbablk,tch,hladdr from x$bh order by tch desc) where rownum <11) a,
(select addr,gets,misses,sleeps from v$latch_children where name= 'cache buffers chains ') b
where a.hladdr=b.addr;
B、找到熱點buffer對應的對象信息:
col owner for a20
col segment_name for a30
col segment_type for a30
select distinct e.owner,e.segment_name,e.segment_type from dba_extents e,
(select * from (select addr,ts#,file#,dbarfil,dbablk,tch from x$bh order by tch desc) where rownum <11) b
where e.relative_fno=b.dbarfil
and e.block_id <=b.dbablk
and e.block_id+e.blocks> b.dbablk;
C、找到操作這些熱點對象的sql語句:
break on hash_value skip 1
select /*+rule*/ hash_value,sql_text from v$sqltext where (hash_value,address) in
(select a.hash_value,a.address from v$sqltext a,(select distinct a.owner,a.segment_name,a.segment_type from dba_extents a,
(select dbarfil,dbablk from (select dbarfil,dbablk from x$bh order by tch desc) where rownum<11) b where a.relative_fno=b.dbarfil
and a.block_id <=b.dbablk and a.block_id+a.blocks> b.dbablk) b
where a.sql_text like '%'||b.segment_name|| '% ' and b.segment_type= 'TABLE ')
order by hash_value,address,piece;
D.根據執行計劃,調整SQL語句。比如的表的連接方式,訪問路徑等。
2、加大表或者索引的PCTFREE,使每個數據塊中存放更少的行。調整PCTFREE時,參數雖然是可以動態調整的,但是隻能對新的數據插入起作用,對於已經填充過滿的老數據塊,是無法起作用的,必須調整參數後,對錶進行重組,才能對錶中的所有數據塊都起作用。表中的行分佈在更多的數據塊上,導致Oracle需要讀取更多的數據塊來完成查詢,大大降低了一個數據塊被重複讀取的概率。降低了數據的性能。
3、減小表空間BLOCK SIZE,使每個數據塊中存放更少的行。如果減小表空間BLOCK SIZE,可能會造成行鏈接,也可能造成性能上影響。
4、使用hash 簇表和使用HASH 分區表,使數據分佈更爲分散.
5、降低程序的併發度,如果程序中使用了parallel查詢,降低parallel degree,以免多個parallel slave同時訪問同樣的數據對象而形成等待降低性能。
6、把經常操作的小表寫入內存。
7、增加hot block上的initrans值。但注意不要把initrans值設置的過於高了,通常設置爲5就足夠了。因爲增加事務意味着要增加ITL事務槽,而每個ITL事務槽將佔用數據塊中24個字節長度。默認情況下,每個數據塊或者索引塊中是ITL槽是2個,在增加initrans的時候,可以考慮增大數據塊所在的表的PCTFREE值,這樣Oracle會利用PCTFREE部分的空間增加ITL slot數量,最大達到maxtrans指定。