runstats是TOM老人家写的一款很好的基准测试小工具,下面简单介绍其安装及使用方法。
一、以sys登录进行授权
grant select on sys.v_$timer to suk;
grant select on v_$mystat to suk;
grant select on sys.v_$statname to suk;
grant select on sys.v_$latch to suk;
二 安装Runstats包
以suk登录,分别执行如下步骤:
1 创建stats视图
create or replace view stats
as
select 'STAT..' || a.name name, b.value
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
union all
select 'LATCH.' || name, gets
from v$latch;
2 创建run_stats临时表
create global temporary table run_stats
( runid varchar2(15),
name varchar2(80),
value int
)on commit preserve rows;
3 创建Runstats包头
create or replace package runstats
as
procedure rs_start;
procedure rs_middle;
procedure rs_stop( p_difference_threshold in number default 0);
end;
p_difference_threshold参数的含义是:前后两个相同的项的统计结果相差的数目的绝对值大于等于该参数设定的值,该统计项才会被显示。默认值是0表示所有的结果都显示。
4 创建Runstats包体
create or replace package body runstats
as
g_start number;
g_run1 number;
g_run2 number;
procedure rs_start
is
begin
delete from run_stats;
insert into run_stats
select 'before', stats.* from stats;
g_start := dbms_utility.get_time;
end;
procedure rs_middle
is
begin
g_run1 := (dbms_utility.get_time-g_start);
insert into run_stats
select 'after 1', stats.* from stats;
g_start := dbms_utility.get_time;
end;
procedure rs_stop(p_difference_threshold in number default 0)
is
begin
g_run2 := (dbms_utility.get_time-g_start);
--add a line here to avoid ora-20000
dbms_output.enable(480000);
dbms_output.put_line
( 'Run1 ran in ' || g_run1 || ' hsecs' );
dbms_output.put_line
( 'Run2 ran in ' || g_run2 || ' hsecs' );
dbms_output.put_line
( 'run 1 ran in ' || round(g_run1/g_run2*100,2) ||
'% of the time' );
dbms_output.put_line( chr(9) );
insert into run_stats
select 'after 2', stats.* from stats;
dbms_output.put_line
( rpad( 'Name', 30 ) || lpad( 'Run1', 12 ) ||
lpad( 'Run2', 12 ) || lpad( 'Diff', 12 ) );
for x in
( select rpad( a.name, 30 ) ||
to_char( b.value-a.value, '999,999,999' ) ||
to_char( c.value-b.value, '999,999,999' ) ||
to_char( ( (c.value-b.value)-(b.value-a.value)), '999,999,999' ) data
from run_stats a, run_stats b, run_stats c
where a.name = b.name
and b.name = c.name
and a.runid = 'before'
and b.runid = 'after 1'
and c.runid = 'after 2'
-- and (c.value-a.value) > 0
and abs( (c.value-b.value) - (b.value-a.value) )
> p_difference_threshold
order by abs( (c.value-b.value)-(b.value-a.value))
) loop
dbms_output.put_line( x.data );
end loop;
dbms_output.put_line( chr(9) );
dbms_output.put_line
( 'Run1 latches total versus runs -- difference and pct' );
dbms_output.put_line
( lpad( 'Run1', 12 ) || lpad( 'Run2', 12 ) ||
lpad( 'Diff', 12 ) || lpad( 'Pct', 10 ) );
for x in
( select to_char( run1, '999,999,999' ) ||
to_char( run2, '999,999,999' ) ||
to_char( diff, '999,999,999' ) ||
to_char( round( run1/run2*100,2 ), '99,999.99' ) || '%' data
from ( select sum(b.value-a.value) run1, sum(c.value-b.value) run2,
sum( (c.value-b.value)-(b.value-a.value)) diff
from run_stats a, run_stats b, run_stats c
where a.name = b.name
and b.name = c.name
and a.runid = 'before'
and b.runid = 'after 1'
and c.runid = 'after 2'
and a.name like 'LATCH%'
)
) loop
dbms_output.put_line( x.data );
end loop;
end;
end;
至此,Runstats包安装完毕。
三、使用
举例如下:
--创建测试表
create table x(id number);
SQL> set serverout on
--记录开始状态
SQL> exec runstats.rs_start;
PL/SQL procedure successfully completed
SQL>
SQL> Begin
2 for i in 1..1000 Loop
3 insert into x values(i);
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed
--记录执行完第一段sql后的状态
SQL> exec runstats.rs_middle;
PL/SQL procedure successfully completed
SQL>
SQL> Begin
2 for i in 1..1000 Loop
3 Execute Immediate 'insert into x values('||i||')';
4 end loop;
5 end;
6 /
PL/SQL procedure successfully completed
--记录执行完第二段sql后的状态,并显示所有的统计结果
SQL> exec runstats.rs_stop;
Run1 ran in 4333 hsecs
Run2 ran in 5825 hsecs
run 1 ran in 74.39% of the time
Name Run1 Run2 Diff
LATCH.job_queue_processes para 0 1 1
LATCH.kwqit: protect wakeup ti 1 2 1
LATCH.ncodef allocation latch 0 1 1
LATCH.session switching 0 1 1
LATCH.transaction branch alloc 0 1 1
STAT..buffer is not pinned cou 3 2 -1
STAT..cleanout - number of ktu 2 3 1
STAT..cluster key scans 1 0 -1
STAT..index fetch by key 1 0 -1
STAT..sorts (rows) 2,409 2,408 -1
STAT..redo ordering marks 3 2 -1
STAT..no work - consistent rea 3 2 -1
STAT..messages sent 1 0 -1
STAT..free buffer requested 19 20 1
STAT..cluster key scan block g 1 0 -1
STAT..calls to kcmgcs 4 5 1
STAT..active txn count during 2 3 1
LATCH.sort extent pool 0 1 1
LATCH.simulator lru latch 1 2 1
LATCH.cache buffer handles 2 4 2
LATCH.object stats modificatio 2 0 -2
STAT..workarea executions - op 10 8 -2
STAT..sorts (memory) 6 4 -2
STAT..change write time 0 2 2
STAT..calls to kcmgas 4 2 -2
LATCH.active checkpoint queue 16 19 3
LATCH.cache buffers lru chain 25 30 5
LATCH.mostly latch-free SCN 14 19 5
LATCH.lgwr LWN SCN 14 19 5
LATCH.channel operations paren 30 36 6
LATCH.library cache load lock 6 0 -6
LATCH.session timer 14 20 6
LATCH.enqueues 69 76 7
STAT..shared hash latch upgrad 7 0 -7
STAT..index scans kdiixs1 7 0 -7
STAT..deferred (CURRENT) block 7 0 -7
STAT..consistent gets - examin 10 3 -7
STAT..commit cleanouts 9 0 -9
STAT..commit cleanouts success 9 0 -9
STAT..enqueue releases 13 4 -9
LATCH.redo writing 56 67 11
STAT..enqueue requests 15 4 -11
STAT..redo entries 1,508 1,495 -13
LATCH.dml lock allocation 35 49 14
STAT..execute count 1,025 1,011 -14
LATCH.redo allocation 1,554 1,569 15
LATCH.session idle bit 53 38 -15
STAT..calls to get snapshot sc 1,024 1,007 -17
LATCH.session allocation 30 52 22
STAT..bytes received via SQL*N 2,541 2,565 24
LATCH.undo global data 34 61 27
STAT..db block changes 3,047 3,020 -27
STAT..db block gets 1,568 1,541 -27
LATCH.messages 124 160 36
LATCH.enqueue hash chains 121 158 37
STAT..parse time cpu 2 39 37
STAT..parse time elapsed 1 45 44
STAT..CPU used by this session 8 59 51
STAT..CPU used when call start 8 59 51
STAT..recursive cpu usage 2 55 53
LATCH.simulator hash latch 1 136 135
STAT..recursive calls 1,139 1,002 -137
LATCH.checkpoint queue latch 760 904 144
LATCH.SQL memory manager worka 938 1,206 268
STAT..session logical reads 1,598 2,551 953
STAT..consistent gets 30 1,010 980
STAT..parse count (total) 24 1,011 987
STAT..opened cursors cumulativ 18 1,011 993
STAT..parse count (hard) 2 1,001 999
LATCH.cache buffers chains 8,096 10,209 2,113
LATCH.row cache objects 32 4,024 3,992
LATCH.row cache enqueue latch 26 4,024 3,998
STAT..redo size 290,276 285,756 -4,520
LATCH.library cache pin alloca 184 6,162 5,978
LATCH.library cache pin 2,342 9,291 6,949
LATCH.child cursor hash table 18 7,007 6,989
LATCH.library cache 2,589 23,497 20,908
LATCH.shared pool 1,386 26,344 24,958
STAT..session uga memory 65,464 0 -65,464
STAT..session pga memory 65,536 0 -65,536
STAT..session pga memory max 327,680 0 -327,680
Run1 latches total versus runs -- difference and pct
Run1 Run2 Diff Pct
18,588 95,205 76,617 19.52%
--从这里可以看出,不绑定变量占用的栓锁是绑定变量的5倍
PL/SQL procedure successfully completed
--如果只想显示同一项的统计值前后差异超过1000的项,则执行
SQL> exec runstats.rs_stop(1000);