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文件的.
语句:
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
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;
其实这个比率就是 (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的话
这条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以上,才是正常的