http://blog.csdn.net/huaishu/article/details/17969909  其它空间估算可参考此方法。

最近发现实时数据库负载很高,数据库日志很多等待事件,检查IO正常,SQL查询也无问题。

发现以前因为undo表空间满添加过文件,添加过好几个表空间文件。


 

如何估算Oracle数据库所需的UNDO表空间的大小
要确定Oracle需要的UNDO 表空间的大小,需要以下三条信息: 

UR 以秒为单位的UNDO_RETENTION
UPS 每秒生成的还原数据块的数量
DBS db_block_size

UndoSpace = [UR * (UPS * DBS)] + (DBS * 24)

UNDO_RETENTION是一个参数,此参数控制为提供读一致性而保留的还原数据量,以秒为单位定义,可以在初始化文件中设置,或使用 ALTER SYSTEM 命令来动态修改。

SQL>ALTER SYSTEM SET UNDO_RETENTION=900;

SQL> show parameter undo_retention

NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
undo_retention integer 900
如果值为900,则可以使还原数据保留 15 分钟,当然需要足够的存储空间才行。

那么如何计算每秒生成的还原数据块的数量呢,可以通过v$undostat视图的begin_time、end_time和undoblks三个字段的值查询出来,计算的SQL语句如下:
SQL> SELECT (UR * (UPS * DBS)) + (DBS * 24) AS "Bytes" FROM (SELECT value AS UR  FROM v$parameter WHERE name = 'undo_retention'),(SELECT (SUM(undoblks)/SUM(((end_time -begin_time)*86400))) AS UPS  FROM v$undostat),  (SELECT value AS DBS FROM v$parameter  WHERE name = 'db_block_size');
 Bytes
----------
445814.844


一般应该在一天中数据库负载最繁重的时候进行计算。
对于UNDO表空间大小的定义需要考虑UNDO_RETNETION参数、产生的UNDO BLOCKS/秒、UNDO BLOCK的大小。undo_retention:对于UNDO表空间的数据文件属性为autoextensible,则undo_retenion参数必须设置,UNDO信息将至少保留至undo_retention 参数设定的值内,但UNDO表空间将会自动扩展。对于固定UNDO表空间,将会通过表空间的剩余空间来最大限度保留UNDO信息。如果FIXED UNDO表空间没有对保留时间作GUARANTEE(alter tablespace xxx retention guarantee;),则undo_retention参数将不会起作用。(警告:如果设置UNDO表空间为retention guarantee,则未过期的数据不会被复写,如果表空间不够则会导致DML操作失败或者transation挂起)


Oracle 10g 有自动Automatic Undo Retention Tuning 这个特性。设置的 undo_retention 参数只是一个指导值,,Oracle 会自动调整 Undo (会跨过 undo_retention 设定的时间) 来保证不会出现 Ora-1555 错误.。通过查询V$UNDOSTAT(该视图记录4天以内的UNDO表空间使用情况,超过4天可以查询DBA_HIST_UNDOSTAT视图) 的 tuned_undoretention (该字段在10G版本才有,9I是没有的)字段可以得到Oracle 根据事务量(如果是文件不可扩展,则会考虑剩余空间)采样后的自动计算出最佳的 retenton 时间.。这样对于一个事务量分布不均匀的数据库来说,,就会引发潜在的问题--在批处理的时候可能 Undo 会用光, 而且这个状态将一直持续, 不会释放。


SQL查询tuned_undoretention:
select to_char(begin_time,'DD-MON-RR HH24:MI') begin_time,to_char(end_time,'DD-MON-RR HH24:MI') end_time,tuned_undoretention from v$undostat order by end_time;


检查一天平均每秒产生的UNDO BLOCK
select (sum(undoblks)/sum((end_time-begin_time)*86400) from v$undostat;
生成的结果是UNDO BLOCK,如果需要计算出实际大小,则需要乘以db_block_size(通过show parameter db_block_size查出来)
如何计算合适的UNDO表空间大小:
select (UR*(UPS*DBS))+(DBS*24) as "bytes" from (select values as UR from v$parameter where name='undo_retention'),(select (sum(undoblks)/sum(((end_time-begin_time)*86400))) as ups from v$undostat),(select values as DBS from v$parameter where name='db_block_size');


 

UNDO I/O性能

1.undo segment头部的争用

Oracle 使用undo segment头部块中一个事务表来跟踪使用它的那些事务,其内容通常被缓存在database buffer cache中以便被搜索。OLTP上很有可能会因为访问这个头部发生等待。

 
  
  1. SQL> select event,total_waits,time_waited,average_wait  

  2.  from v$system_event where event like '%undo%' and event like '%slot%';  

 

average_wait:平均每毫秒等待的次数,等于0或接近于0最好。
 
  
  1. SQL>select class,count from v$waitstat  

  2. where class in ('undo header','system undo header');  

 

count:等候访问undo segment头部的次数。理想情况下,该值等于0或接近于0最好。
 
  
  1. SQL>select n.name,s.usn,  

  2. decode(s.waits,0,1,1-(s.waits/s.gets)) "RBS Header Get Ratio"  

  3. from v$rollstat s,v$rollname n  

  4. where s.usn = n.usn  

  5. order by usn;  

RBS Header Get Ratio:等于1或接近1最好,至少为95%。

2.undo segment范围的争用

 
  
  1. SQL>select class,count from v$waitstat  

  2. where class ='system undo block' ;  

 

count:系统回滚段的范围的块争用次数。
 
  
  1. SQL>select w.count,w.count/s.value as wait_ratio from v$waitstat w,v$sysstat s  

  2. where w.class = 'undo block'

  3. and s.name = 'consistent gets';  

count:非系统回滚段的范围的块争用次数。

wait_ratio:回滚等待率,如果超过1%,则需要调整了。

3.undo segment的环绕

 
  
  1. SQL> select n.name,s.usn,  

  2. decode(s.waits,0,1,1-(s.waits/s.gets)) "RBS Header Get Ratio",s.wraps  

  3. from v$rollstat s,v$rollname n  

  4. where s.usn = n.usn  

  5. order by usn;  

s.wraps:该回滚段被环绕到下一个范围的次数。次数太多表示段范围可能太小。

4.undo segment的动态范围分配

事务的像前版本在undo segment中发生环绕,而下一个范围已经分配给其他事务的像前版本,此时会在它们之间动态创建一个范围来给该事务的像前版本环绕。应避免,以减少I/O。

 
  
  1. SQL> select event,total_waits,time_waited,average_wait  

  2. from v$system_event where event = 'undo segment extension';  

 

time_waited:表示动态分配的等待次数。若值很高或不断增长,说明undo segment太少或太小。
 
  
  1. SQL>select n.name,s.usn,s.extends,  

  2. decode(s.waits,0,1,1-(s.waits/s.gets)) "RBS Header Get Ratio",s.wraps  

  3. from v$rollstat s,v$rollname n  

  4. where s.usn = n.usn  

  5. order by usn;  

 

s.extends:被动态添加的范围数。若经常发生动态添加,则说明undo segment可能太小。