(tom大师的)定制脚本runstat和mystat和show_space

Runstat需要访问的几个视图:
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
union all
select 'STAT...Elapsed Time', hsecs from v$timer;




runstat临时小表,用于收集统计信息:

create global temporary table run_stats
( runid varchar2(15),
name varchar2(80),
value int )
on commit preserve rows;


最后创建runstat包,

It contains three simple API calls:
• RS_START (Runstats Start) to be called at the beginning of a Runstats test
• RS_MIDDLE to be called in the middle, as you might have guessed
• RS_STOP to finish off and print the report

 

create or replace package runstats_pkg as
  procedure rs_start;
  procedure rs_middle;
  procedure rs_stop(p_difference_threshold in number default 0);
end;
/
Package created.


下面是包体:


create or replace package body runstats_pkg 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_cpu_time;
  end;


  procedure rs_middle is
  begin
    g_run1 := (dbms_utility.get_cpu_time - g_start);
  
    insert into run_stats
      select 'after 1', stats.* from stats;
    g_start := dbms_utility.get_cpu_time;
  
  end;


  procedure rs_stop(p_difference_threshold in number default 0) is
  begin
    g_run2 := (dbms_utility.get_cpu_time - g_start);
  
    dbms_output.put_line('Run1 ran in ' || g_run1 || ' cpu hsecs');
    dbms_output.put_line('Run2 ran in ' || g_run2 || ' cpu hsecs');
    if (g_run2 <> 0) then
      dbms_output.put_line('run 1 ran in ' ||
                           round(g_run1 / g_run2 * 100, 2) ||
                           '% of the time');
    end if;
    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 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 /
                                   decode(run2, 0, to_number(0), 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;



Mystat脚本:
Mystat.sql和相应的mystat2.sql用于展示完成操作之前和之后的某些oracle“统计结果”的变化情况。Mystat.sql只是获得统计结果的开始值:
Mystat.sql

set echo off
set verify off
column value new_val V
define S="&1"
set autotrace off
select a.name, b.value
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
and lower(a.name) like '%' || lower('&S')||'%'
/
set echo on


mystat2.sql用于报告差值(通过运行第一个脚本mystat.sql来填充&V,为此它使用了SQL*PLUS NEW_VAL特性,其中包含由上一个查询选择的最后一个value)
mystat2.sql

set echo off
set verify off
select a.name, b.value V, to_char(b.value-&V,'999,999,999,999') diff
from v$statname a, v$mystat b
where a.statistic# = b.statistic#
and lower(a.name) like '%' || lower('&S')||'%'
/
set echo on

例如:要查看某个UPDATE生成的redo数,可以使用以下命令:

big_table@ORA11GR2> @mystat "redo size"
big_table@ORA11GR2> set echo off
NAME VALUE
------------------------------ ----------
redo size 496
big_table@ORA11GR2> update big_table set owner = lower(owner)
2 where rownum <= 1000;
1000 rows updated.
big_table@ORA11GR2> @mystat2
big_table@ORA11GR2> set echo off
NAME V DIFF
------------------------------ ---------- ----------------
redo size 89592 89,096


This shows our UPDATE of 1,000 rows generated 89,096 bytes of redo.
1000行记录的update会产生89096字节的redo;

SHOW SPACE
用于打印数据库段的空间利用率信息,其接口如下:

ops$tkyte@ORA11GR2> desc show_space
PROCEDURE show_space
Argument  Name Type In/Out Default?
------------------------------ ----------------------- ------ --------
P_SEGNAME VARCHAR2   IN
P_OWNER   VARCHAR2   IN    DEFAULT
P_TYPE    VARCHAR2   IN    DEFAULT
P_PARTITION VARCHAR2 IN    DEFAULT


The arguments are as follows:
• P_SEGNAME - Name of the segment—the table or index name, for example.
• P_OWNER - Defaults to the current user, but you can use this routine to look at some other schema.
• P_TYPE - Defaults to TABLE and represents the type of object you are looking at. For example,
select distinct segment_type from dba_segments lists valid segment types.
• P_PARTITION - Name of the partition when you show the space for a partitioned object. SHOW_SPACE
shows space for only a partition at a time.


一个例子的输出如下:这里段位于一个自动段空间管理(Automatic Segment
Space Management,ASSM)(下面的big_table在后面有脚本)

big_table@ORA11GR2> exec show_space('BIG_TABLE');
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 0
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 0
Full Blocks ..................... 14,469
Total Blocks............................ 15,360
Total Bytes............................. 125,829,120
Total MBytes............................ 120
Unused Blocks........................... 728
Unused Bytes............................ 5,963,776
Last Used Ext FileId.................... 4
Last Used Ext BlockId................... 43,145
Last Used Block......................... 296




The items reported are as follows:
• Unformatted Blocks – The number of blocks that are allocated to the table below the high water
mark, but have not been used. Add unformatted and unused blocks together to get a total count
of blocks allocated to the table but never used to hold data in an ASSM object.
• FS1 Blocks-FS4 Blocks – Formatted blocks with data. The ranges of numbers after their name
represent the emptiness of each block. For example, (0-25) is the count of blocks that are between
0 and 25 percent empty.
• Full Blocks – The number of blocks that are so full that they are no longer candidates for future
inserts.
• Total Blocks, Total Bytes, Total Mbytes - The total amount of space allocated to the segment
measured in database blocks, bytes, and megabytes.
• Unused Blocks, Unused Bytes – Represents a portion of the amount of space never used. These are
blocks allocated to the segment but are currently above the high water mark of the segment
• Last Used Ext FileId – The file ID of the file that contains the last extent that contains data.
• Last Used Ext BlockId – The block ID of the beginning of the last extent; the block ID within the
last-used file.
• Last Used Block – The block ID offset of the last block used in the last extent.


如果对象在用户空间管理的表空间中,使用show_space查看时:


big_table@ORA11GR2> exec show_space( 'BIG_TABLE' )
Free Blocks............................. 1
Total Blocks............................ 147,456
Total Bytes............................. 1,207,959,552
Total MBytes............................ 1,152
Unused Blocks........................... 1,616
Unused Bytes............................ 13,238,272
Last Used Ext FileId.................... 7
Last Used Ext BlockId................... 139,273
Last Used Block......................... 6,576
PL/SQL procedure successfully completed.


这里唯一的区别是报告中最前面的free blocks项,这是段的第一个freelist(自由列表)组中的块数,

create or replace procedure show_space(p_segname   in varchar2,
                                       p_owner     in varchar2 default user,
                                       p_type      in varchar2 default 'TABLE',
                                       p_partition in varchar2 default NULL)
-- this procedure uses authid current user so it can query DBA_*
  -- views using privileges from a ROLE and so it can be installed
  -- once per database, instead of once per user that wants to use it
authid current_user as
  l_free_blks          number;
  l_total_blocks       number;
  l_total_bytes        number;
  l_unused_blocks      number;
  l_unused_bytes       number;
  l_LastUsedExtFileId  number;
  l_LastUsedExtBlockId number;
  l_LAST_USED_BLOCK    number;
  l_segment_space_mgmt varchar2(255);
  l_unformatted_blocks number;
  l_unformatted_bytes  number;
  l_fs1_blocks         number;
  l_fs1_bytes          number;
  l_fs2_blocks         number;
  l_fs2_bytes          number;
  l_fs3_blocks         number;
  l_fs3_bytes          number;
  l_fs4_blocks         number;
  l_fs4_bytes          number;
  l_full_blocks        number;
  l_full_bytes         number;
  -- inline procedure to print out numbers nicely formatted
  -- with a simple label
  procedure p(p_label in varchar2, p_num in number) is
  begin
    dbms_output.put_line(rpad(p_label, 40, '.') ||
                         to_char(p_num, '999,999,999,999'));
  end;
begin
  -- this query is executed dynamically in order to allow this procedure
  -- to be created by a user who has access to DBA_SEGMENTS/TABLESPACES
  -- via a role as is customary.
  -- NOTE: at runtime, the invoker MUST have access to these two
  -- views!
  -- this query determines if the object is an ASSM object or not
  begin
    execute immediate 'select ts.segment_space_management
from dba_segments seg, dba_tablespaces ts
where seg.segment_name = :p_segname
and (:p_partition is null or
seg.partition_name = :p_partition)
and seg.owner = :p_owner
and seg.tablespace_name = ts.tablespace_name'
      into l_segment_space_mgmt
      using p_segname, p_partition, p_partition, p_owner;
  exception
    when too_many_rows then
      dbms_output.put_line('This must be a partitioned table, use p_partition => ');
      return;
  end;
  -- if the object is in an ASSM tablespace, we must use this API
  -- call to get space information, else we use the FREE_BLOCKS
  -- API for the user managed segments
  if l_segment_space_mgmt = 'AUTO' then
    dbms_space.space_usage(p_owner,
                           p_segname,
                           p_type,
                           l_unformatted_blocks,
                           l_unformatted_bytes,
                           l_fs1_blocks,
                           l_fs1_bytes,
                           l_fs2_blocks,
                           l_fs2_bytes,
                           l_fs3_blocks,
                           l_fs3_bytes,
                           l_fs4_blocks,
                           l_fs4_bytes,
                           l_full_blocks,
                           l_full_bytes,
                           p_partition);
  
    p('FS1 Blocks (0-25) ', l_fs1_blocks);
    p('FS2 Blocks (25-50) ', l_fs2_blocks);
    p('FS3 Blocks (50-75) ', l_fs3_blocks);
    p('FS4 Blocks (75-100)', l_fs4_blocks);
    p('Full Blocks ', l_full_blocks);
  else
    dbms_space.free_blocks(segment_owner     => p_owner,
                           segment_name      => p_segname,
                           segment_type      => p_type,
                           freelist_group_id => 0,
                           free_blks         => l_free_blks);
    p('Free Blocks', l_free_blks);
  end if;
  -- and then the unused space API call to get the rest of the
  -- information
  dbms_space.unused_space(segment_owner             => p_owner,
                          segment_name              => p_segname,
                          segment_type              => p_type,
                          partition_name            => p_partition,
                          total_blocks              => l_total_blocks,
                          total_bytes               => l_total_bytes,
                          unused_blocks             => l_unused_blocks,
                          unused_bytes              => l_unused_bytes,
                          LAST_USED_EXTENT_FILE_ID  => l_LastUsedExtFileId,
                          LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
                          LAST_USED_BLOCK           => l_LAST_USED_BLOCK);
  p('Total Blocks', l_total_blocks);
  p('Total Bytes', l_total_bytes);
  p('Total MBytes', trunc(l_total_bytes / 1024 / 1024));
  p('Unused Blocks', l_unused_blocks);
  p('Unused Bytes', l_unused_bytes);
  p('Last Used Ext FileId', l_LastUsedExtFileId);
  p('Last Used Ext BlockId', l_LastUsedExtBlockId);
  p('Last Used Block', l_LAST_USED_BLOCK);
end;
/

Big_table脚本:

create table big_table
as
select rownum id, a.*
from all_objects a
where 1=0
/
alter table big_table nologging;
declare
l_cnt number;
l_rows number := &1;
begin
insert /*+ append */
into big_table
select rownum, a.*
from all_objects a
where rownum <= &1;
l_cnt := sql%rowcount;
commit;
while (l_cnt < l_rows)
loop
insert /*+ APPEND */ into big_table
select rownum+l_cnt,
OWNER, OBJECT_NAME, SUBOBJECT_NAME, OBJECT_ID, DATA_OBJECT_ID,
OBJECT_TYPE, CREATED, LAST_DDL_TIME, TIMESTAMP, STATUS,
TEMPORARY, GENERATED, SECONDARY, NAMESPACE, EDITION_NAME
from big_table
where rownum <= l_rows-l_cnt;
l_cnt := l_cnt + sql%rowcount;
commit;
end loop;
end;
/

 

alter table big_table add constraint
big_table_pk primary key(id);


exec dbms_stats.gather_table_stats( user, 'BIG_TABLE', estimate_percent=> 1);

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值