Oracle - 使用各种SQL来熟知buffer cache使用情况
http://v.youku.com/v_show/id_XMzkyMjE3NTA0.html
所做的學習筆記
1. 查看某個對象所占用buffer狀態:
上一章提過了, 使用如下語句:
select?o.object_name,?
???????decode(state, 0, 'free', 1, 'xcur' , 2, 'scur', 3, 'cr',?
???????????????????? 4, 'read', 5, 'mrec' , 6, 'irec', 7, 'write',?
???????????????????? 8, 'pi')?as?state,?
?????? count(1) blocks?
from?x$bh b, dba_objects o?
where?b.obj = o.data_object_id?
??and?o.object_name = 'CL_DEPT'?
??and?o.owner = 'HR'?
group by?o.object_name, state?
order by?blocks?desc;
如圖:
?
如圖, 表hr.cl_dept占用6個 xcur狀態的buffer, 3個cr狀態的buffer啦.
2. 查看某個對象所占用buffer所對應的dbf文件中的block
使用如下語句:
select?object_name, DBARFIL, DBABLK?
from?x$bh a, dba_objects b
where?a.obj = b.data_object_id?
and?b.object_name = 'CL_DEPT'
and?b.owner= 'HR';
其中視圖x$bh中 DBARFIL 就是知dbf文件編號啦, 而DBABLK就是block的編號
如下圖:
可以見到相應地有9個buffer, 但是實際上只有6個 DBABLK編號哦, 因為9個buffer中只有6個xcur狀態的buffer啦, 而3個CR 塊是不對應dbf文件的.
?可以用下面命令來查看數據文件編號啦
?3. 查看具體某個BLOCK對應buffer狀態 ? 既然上面已經獲得了數據文件編號和block的編號, 就可以在x$bh中查看某個BLOCK的狀態了.
語句:
select?DBARFIL, DBABLK, STATE?from?x$bh
where?DBARFIL = 4
and?? DBABLK = 175;
可以見到, 在4號dbf文件中, 175編號的block在buffer cache里有4個相關的buffer, 其中只會有1個是狀態是xcur的, 其余3個的state是3, 就是3個CR塊啦.
?4. 查看buffer cache所有對象的buffer占用狀態
?? 其實就是第一條sql語句作一些修改就得啦, 不過既然老相老師有講, 我也寫出來吧.
select?o.object_name,?
???????decode(state, 0, 'free', 1, 'xcur' , 2, 'scur', 3, 'cr',?
???????????????????? 4, 'read', 5, 'mrec' , 6, 'irec', 7, 'write',?
???????????????????? 8, 'pi')?as?state,?
?????? count(1) blocks?
from?x$bh b, dba_objects o?
where?b.obj = o.data_object_id?
group by?o.object_name, state?
order by?o.object_name, state?
group by?o.object_name, state ?
?注意, 如果對blocks這個列排序, 就知道baffer_cache哪個對象占用數據最多啦~
5. 查找熱塊
???? 首先說明一下什么是熱塊,? 之前已經介紹過在buffer cache里所有干凈的buffer都會被掛在LRU鏈, 按照訪問次數(邏輯讀次數)排序,次數多的在熱端,? 次數少的在冷端. 所以實在上就是查找訪問次數最多的幾個buffer
???? 而在x$bh中包含了所有buffers的信息, 其中TCH列意思就是touch, 1個buffer每被邏輯讀一次,那么TCH的值就加1,? 所以只需按照這個值排序就ok了.
???? 命令如下:
select
??????? o.object_name,??
??????? b.dbarfil file#,
??????? b.dbablk? block#,
??????? b.tch???? touches
from????x$bh b, dba_objects o
where?? b.obj = o.data_object_id
and???? b.tch >0
order by?b.tch;
?
可以見到 JOB$ 這個對象在1號數據文件中2008 和 2008號block 被訪問次數最多, 邏輯讀發生244次啦~
6. 查找數據庫文件所有block的總數
?? 呢個好簡單:
select sum(blocks) from dba_data_files;
?
? 7. 查看buffer cache可以使用比率
???? 其實這個比率就是 (free buffers的數量+ 干凈buffer的數量 )/ buffer的總數
???? free buffer在 x$bh 中的state 是0, 我們可以根據這個判斷.
???? 那么state不是0的可分成干凈的和臟的,?? 我們可以用lrba_seq這個字段來判斷
???? lrba_seq意思是臟buffer第一次變臟時所對應的redo entries在redo log file里的位置.
???可以根據lrba_seq來判斷,如果lrba_seq=0,?則說明這個buffer是干凈的, 否則是臟的
???
下面這個語句分別列出buffer cache里?空閑,干凈,臟的buffer的數量
select decode(state, 0, 'free',
????????????????????decode(lrba_seq, 0, 'AVAILABLE',
??????????????????????????????????????? 'BEING USED'))?as?Block_status,
???????count(1) as Count
from?x$bh
group by decode(state, 0, 'free',
???????????????????????decode(lrba_seq, 0, 'AVAILABLE',
???????????????????????????????????????? 'BEING USED'));
如下圖: 可以見到干凈buffer 有15個(生產中最好控制在10%以內), SGA太大沒好處啦
???????? 臟的有23個, 證明物理IO讀取很少啦.
? ?
8. 查看前10條最耗緩存(邏輯IO最多)的sql語句所占的緩存比率.
??? 在生產中這個比例最好控制在5%以內.
????使用如下語句:
???
select sum(pct_bufgets)?as?Percent
from?? (select?rank()?over?(order by?buffer_gets?desc)?as?rank_bufgets,
???????????????to_char(100 *?ratio_to_report(buffer_gets)?over?(), '999.99')?as?pct_bufgets
????????from?v$sqlarea)
where?rank_bufgets < 11;
簡單解析下上面語句啦~
其中rank 是oracle的1個排名的函數,? 返回1個排名的值, over()是rank的1個附加條件,
rank()?over?(order by?buffer_gets?desc)??的意思就是返回1個值,? 這個值是按照buffer_gets倒序排列的排名整數.
詳細用法可以參考這里:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions141.htm#SQLRF00690
而ratio_to_report 是 oracle的另1個函數,?作用是返回1個字段的值占這張表這個字段的所有值的比率.?也可以通過over()附加條件..
100 *?ratio_to_report(buffer_gets)?over?()??的意思就是返回某一行buffer_gets值在表里所占的比率啦~
詳細用法可以參考這里:
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions124.htm
而 v$sqlarea?中的字段 buffer_gets就是邏輯讀次數的意思啦
執行如下圖: 這個比率太大了, 因為是學習用數據庫嘛
?
如果在生產數據庫中,這個數字很大, 例如20%以上, 說明有用戶執行了若干個占用緩存很大的sql了, 一般來講執行這種規模的sql語句會托慢數據庫的啦.
9. 查看前10條物理IO最多sql語句
???select?disk_reads,?substr(sql_text,1,4000)?from?v$sqlarea
???where?rownum <= 10?order by?disk_reads?desc;
對應buffer_gets,??? v$sqlarea 字段disk_reads就算物理讀次數啦.
所以
???select?buffer_gets,?substr(sql_text,1,4000)?from?v$sqlarea
???where?rownum <= 10?order by?buffer_gets?desc;
就是查看邏輯讀次數最多的10條sql.
其實在操作系統級別也有很多工具來查看物理IO的狀態啦.
例如:
iostat
vmstat
?
top
mpstat
? 這個只查看cpu狀態的,??? mpstat -P n 可以用來查看第n個cpu的狀態,? 如果系統有多cpu的話
?
?
?10. 查看buffer_cache每個對象具體占用情況
????????
這條sql語句就復9雜了, 我在視頻上也抄不下來, 幸好甲骨論論壇能找到下載, 老相好人啊.
SELECT?/*+ ORDERED USE_HASH(o u) MERGE */
?DECODE(obj#,
????????NULL,
????????to_char(bh.obj),
??????? u.name || '.' || o.name) name,
?COUNT(*)?total,
?SUM(DECODE((DECODE(lru_flag, 8, 1, 0) +?DECODE(SIGN(tch - 2), 1, 1, 0)),? /*sign用來判斷數值的正負*/
??????????? 2, 1,
??????????? 1,1,
??????????? 0))?hot,
?SUM(DECODE(DECODE(SIGN(lru_flag - 8), 1, 0, 0, 0, 1) +DECODE(tch, 2, 1, 1, 1, 0, 1, 0),
??????????? 2,1,
??????????? 1,0,
??????????? 0))?cold,
?SUM(DECODE(BITAND(flag,?POWER(2, 19)), 0, 0, 1))?fts,? /*BITAND函數請見下面注1,POWER函數見注2*/
?SUM(tch)?total_tch,
?ROUND(AVG(tch), 2)?avg_tch,? /*round 是四舍5入函數啦*/
?MAX(tch)?max_tch,
?MIN(tch)?min_tch
??FROM?x$bh bh, sys.obj$ o, sys.user$ u
?WHERE
??? bh.obj <> 4294967295
???AND?bh.state in (1, 2, 3)
???AND?bh.obj = o.dataobj#(+)
???AND?bh.inst_id = USERENV('INSTANCE')
?AND?o.owner# = u.user#(+)
--?? AND o.owner# > 5
???AND?u.name NOT like 'AURORA$%'
?GROUP BY DECODE(obj#,
???????????????? NULL,
?????????????????to_char(bh.obj),
???????????????? u.name || '.' || o.name)
?ORDER BY??total?desc
?/
注1:
BITAND函數? 返回兩個數值按位 AND運算的結果, 返回的值是十進制..
?BITAND(??? )??? 將??? nExpression1??? 的每一位同??? nExpression2??? 的相應位進行比較。如果??? nExpression1??? 和??? nExpression2??? 的位都是??? 1,相應的結果位就是??? 1;否則相應的結果位是??? 0。?
例如 BITAND(6,3) 的結果是2.??? 因為6的2進制是110, 3是011, 所以and后是 010 就是2啦..
詳細請參考:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions021.htm#SQLRF00612
注2:
POWER函數就是指數函數啦, 例如Power(3,2) 就是等于3的2次方=9?? 如果底數小于0 冪必須是整數
可以參考:
http://docs.oracle.com/cd/E11882_01/server.112/e26088/functions129.htm#SQLRF00689
執行效果如下圖:
?
?11.?匯總buffer_cache每個對象的各狀態buffer個數
這條語句就簡單多啦~
SELECT?t.name?AS?tablespace_name,
?????? o.object_name,
???????SUM(DECODE(bh.status, 'free', 1, 0))?AS?free,
???????SUM(DECODE(bh.status, 'xcur', 1, 0))?AS?xcur,
???????SUM(DECODE(bh.status, 'scur', 1, 0))?AS?scur,
???????SUM(DECODE(bh.status, 'cr', 1, 0))?AS?cr,
???????SUM(DECODE(bh.status, 'read', 1, 0))?AS?read,
???????SUM(DECODE(bh.status, 'mrec', 1, 0))?AS?mrec,
???????SUM(DECODE(bh.status, 'irec', 1, 0))?AS?irec
FROM?? v$bh bh
???????JOIN?dba_objects o?ON?o.data_object_id = bh.objd
???????JOIN?v$tablespace t?ON?t.ts# = bh.ts#
GROUP BY?t.name, o.object_name
order by?xcur desc
效果如下圖:
??
?12.?查看buffer_cache每個對象占用多少個buffer, 有多少block被緩存到buffer cache中.
????? 呢個就犀利了, 首先要創建1個試圖buffer map
create or replace view?buffer_map?as
select
?? o.owner????????? owner,
?? o.object_name??? object_name,
?? o.subobject_name subobject_name,
?? o.object_type??? object_type,
???count(distinct file# || block#)???????? num_blocks
from
?? dba_objects? o,
?? v$bh???????? bh
where
?? o.data_object_id? = bh.objd
-- and? o.owner not in ('SYS','SYSTEM')
and
?? bh.status != 'free'
group by
?? o.owner,
?? o.object_name,
?? o.subobject_name,
?? o.object_type
order by
???count(distinct file# || block#)?desc
;
跟住就可以用下面語句查詢了~
column c0 heading "Owner"??????????????????????????????????? format a12
column c1 heading "Object|Name"????????????????????????????? format a30
column c2 heading "Object|Type"????????????????????????????? format a8
column c3 heading "Number of|Blocks in|Buffer|Cache"???????? format 99,999,999
column c4 heading "Percentage|of object|blocks in|Buffer"??? format 999
column c5 heading "Buffer|Pool"????????????????????????????? format a7
column c6 heading "Block|Size"?????????????????????????????? format 99,999
?
select
?? buffer_map.owner????????????????????????????????????????? c0,
?? object_name?????????????????????????????????????? c1,
?? case when object_type = 'TABLE PARTITION' then 'TAB PART'
??????? when object_type = 'INDEX PARTITION' then 'IDX PART'
??????? else object_type end c2,
?? sum(num_blocks)???????????????????????????????????? c3,
?? (sum(num_blocks)/greatest(sum(blocks), .001))*100 c4,
?? buffer_pool?????????????????????????????????????? c5,
?? sum(bytes)/sum(blocks)??????????????????????????? c6
from
?? buffer_map,
?? dba_segments s
where
?? s.segment_name = buffer_map.object_name
and
?? s.owner = buffer_map.owner
and
?? s.segment_type = buffer_map.object_type
and
?? nvl(s.partition_name,'-') = nvl(buffer_map.subobject_name,'-')
group by
?? buffer_map.owner,
?? object_name,
?? object_type,
?? buffer_pool
having
?? sum(num_blocks) > 10
order by
?? sum(num_blocks) desc
;
下面是效果圖:
?13.?查看buffer_cache當前命中率.
???? 緩存命中率的定義之前都提過啦, 就是緩存中邏輯讀的次數/ 邏輯讀+ 物理讀的總次數.
語句如下:
select?(1 -(sum(decode(name, 'physical reads',value,0))/
???????? (sum(decode(name, 'db block gets',value,0))? +?sum(decode(name,'consistent gets',value,0))))
???????? )* 100?as?Hit_Radio
?????????from?v$sysstat;
解析一下:
官方在線文檔基本的定義為如下:
DB block gets:the number of accesses to the current image of a block
Consistent gets:the number of accesses to a read-consistent image of a block
Physical reads:the number of blocks read from disk
這 其中主要涉及到了Oracle讀取數據的consistent mode和current mode這兩個模式,對于db block gets是在current mode下讀取的block數目(單位應該是“塊次”,同一個block讀取了兩個算做2),而consistent gets是在consistent mode下讀取的block數目(單位同上)。
current mode下讀取數據是為了保證讀取到的數據是當前時間點上最新的數據,這樣做的目的一般都是為了DML語句的需求,比如需要更新,自然需要知道最新的數據 才行;consistent mode呢主要是為了保證Oracle數據一致讀的特性,一般都是在select情況下發生,讀到的數據可能是一個實際存在的block,也有可能需要根 據scn信息以及transaction相關信息以及回滾段中數據來構造。
而physical reads是與logical reads相對的一個概念,兩者的區別是讀取的數據是從buffer中讀取到還是從disk上的db file中取到。通過v$sysstat也可以看到,里面還有db block gets from cache以及consistent gets from cache兩項,且這兩項的數值與db block gets和consistent gets并不相同且小于后兩者。所以不管是db block gets還是consistent gets,都可能出現了physical reads和logical reads兩種情況(由buffer中的是否已經存在需要的數據),也即是說,db block gets與consistent gets兩者已經構成了一次數據庫操作中讀取的所有block的總次數了。因此,logical reads自然也就可以通過如下公式算的:logical reads = (db block gets + consistent gets) - physical reads。
注,上面3段轉自:http://fengyaping1210.itpub.net/post/39890/486348
執行一下:
在生產中, 這個值一般在98以上,才是正常的
?
?仲有好多, 老相老師話以后再詳細講~
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀
總結
以上是生活随笔為你收集整理的Oracle - 使用各种SQL来熟知buffer cache使用情况的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 转:linux svn常用命令
- 下一篇: Oracle中的Rowid