oracle 11g表空间使用率统计心得
2016-02-05 17:24
621 查看
oracle 11g表空间使用统计
本文研究有关oracle表空间统计的相关手段传统的oracle表空间统计
oracle11g新增表空间统计视图
x$kttets
v$filespace_usage
sys.WRH$_TABLESPACE_SPACE_USAGE
保证快速及准确的查询表空间
传统的oracle表空间统计
传统的oracle表空间的统计是通过查询视图dba_data_files及dba_free_space统计出来的例如这样:
select tb1.Tablespace_name "Tablespace_name", decode(sign(tb2.Sizes-0.99),1,round(tb2.Sizes,2) || 'GB',round(tb2.Sizes*1024,2) || 'MB') "Size", decode(sign((tb2.Sizes-tb1.Free)-0.99),1,round((tb2.Sizes-tb1.Free),2) || 'GB',round((tb2.Sizes-tb1.Free)*1024,2) || 'MB') "Used", decode(sign(tb1.Free-0.99),1,round(tb1.Free,2) || 'GB',round(tb1.Free*1024,2) || 'MB') "Free", decode(sign(tb2.Max-0.99),1,round(tb2.Max,2) || 'GB',round(tb2.Max*1024,2) || 'MB') "Max", to_number(round(((tb2.Sizes-tb1.Free)/tb2.Sizes)*100,2)) "Usage%", to_number(round(((tb2.Sizes-tb1.Free)/tb2.Max)*100,2)) "Usageofmax%" from (select tablespace_name, round(sum(bytes)/power(2, 30),2) as Free from dba_free_space group by tablespace_name) tb1, (select tablespace_name, round(sum(user_bytes)/power(2, 30),2) as Sizes, round(sum(decode(autoextensible,'YES',maxbytes,'NO',bytes)/power(2, 30))) as Max from dba_data_files group by tablespace_name) tb2 where tb1.Tablespace_name=tb2.Tablespace_name;
这个查询无论数据文件是自增长还是非自增长的,统计的都是最准确的,因为dba_free_space的数据来源自最基础的系统表,准确性毋庸置疑。
但是在实际的使用过程中,我在某些数据库查询时,这条语句执行的非常缓慢,原因是dba_free_space的行数太多了,例如这样的解释计划:
| Id | Operation | Name | Rows | Bytes | TempSpc| Cost (%CPU)| Time | …… | 26 | VIEW | | 16 | 480 | | 3036K(100)| 10:07:17 | | 27 | HASH GROUP BY | | 16 | 352 | | 3036K(100)| 10:07:17 | | 28 | VIEW | DBA_FREE_SPACE | 10353 | 222K| | 3036K(100)| 10:07:17 | …… | 40 | NESTED LOOPS | | 10275 | 1073K| | 3036K(100)| 10:07:16 | | 41 | NESTED LOOPS | | 95085 | 9285K| | 3036K(100)| 10:07:16 | |* 42 | HASH JOIN | | 398K| 13M| 8600K| 3003 (1)| 00:00:37 | …… Statistics ---------------------------------------------------------- 420830 recursive calls 3626 db block gets 863221 consistent gets 3699 physical reads 0 redo size 1745 bytes sent via SQL*Net to client 524 bytes received via SQL*Net from client 2 SQL*Net roundtrips to/from client 0 sorts (memory) 0 sorts (disk) 15 rows processed
由于dba_free_space的行数加上group by的原因,竟然有86W次的逻辑读,在这里查询耗费了大量的时间,时间长达30秒或者更多
递归查询次数竟然有42W次,如你所见,这里耗费了20秒,最后整个查询有50多秒,真的让人崩溃。
select max(rownum) from dba_free_space;;这里统计出dba_free_space的行数超过19W条。于是我开始寻找其他办法解决这个烦人的问题。
oracle11g新增表空间统计视图
DBA_TABLESPACE_USAGE_METRICS describes tablespace usage metrics for all types of tablespaces, including permanent, temporary, and undo tablespaces. —— [ Oracle在线文档 ]DBA_TABLESPACE_USAGE_METRICS 视图给出了答案
select * from dba_tablespace_usage_metrics;
TABLESPACE_NAME | USED_SPACE | TABLESPACE_SIZE | USED_PERCENT |
---|---|---|---|
DATABAK | 396538250 | 402669384 | 98.4773777 |
GZCDR | 96887456 | 2684354560 | 3.609339 |
GZ e4d9 UNIBPMN | 2856 | 67108832 | .004255774 |
统计结果跟传统的方法在99%的情况下无二致
我们来看一下DBA_TABLESPACE_USAGE_METRICS 视图的定义
CREATE OR REPLACE VIEW SYS.DBA_TABLESPACE_USAGE_METRICS AS SELECT t.name, tstat.kttetsused, tstat.kttetsmsize, (tstat.kttetsused / tstat.kttetsmsize) * 100 FROM sys.ts$ t, x$kttets tstat WHERE t.online$ != 3 and t.bitmapped <> 0 and t.contents$ = 0 and bitand(t.flags, 16) <> 16 and t.ts# = tstat.kttetstsn union SELECT t.name, sum(f.allocated_space), sum(f.file_maxsize), (sum(f.allocated_space)/sum(f.file_maxsize))*100 FROM sys.ts$ t, v$filespace_usage f WHERE t.online$ != 3 and t.bitmapped <> 0 and t.contents$ <> 0 and f.flag = 6 and t.ts# = f.tablespace_id GROUP BY t.name, f.tablespace_id, t.ts# union SELECT t.name, sum(f.allocated_space), sum(f.file_maxsize), (sum(f.allocated_space)/sum(f.file_maxsize))*100 FROM sys.ts$ t, gv$filespace_usage f, gv$parameter param WHERE t.online$ != 3 and t.bitmapped <> 0 and f.inst_id = param.inst_id and param.name = 'undo_tablespace' and t.name = param.value and f.flag = 6 and t.ts# = f.tablespace_id GROUP BY t.name, f.tablespace_id, t.ts#; comment on table SYS.DBA_TABLESPACE_USAGE_METRICS is 'Description of all tablespace space usage metrics'; comment on column SYS.DBA_TABLESPACE_USAGE_METRICS.TABLESPACE_NAME is 'Tablespace name'; comment on column SYS.DBA_TABLESPACE_USAGE_METRICS.USED_SPACE is 'Total space consumed in the tablespace'; comment on column SYS.DBA_TABLESPACE_USAGE_METRICS.TABLESPACE_SIZE is 'Total size of the tablespace'; comment on column SYS.DBA_TABLESPACE_USAGE_METRICS.USED_PERCENT is '% of used space, as a function of maximum possible tablespace size';
主要是从
x$kttets系统表和
v$filespace_usage视图取数据
显然我们从这张视图查表空间使用情况的速度快多了
事实也是如此
Elapsed: 00:00:00.78 …… Statistics ---------------------------------------------------------- 80 recursive calls 0 db block gets 49438 consistent gets 0 physical reads 0 redo size 1694 bytes sent via SQL*Net to client 535 bytes received via SQL*Net from client 3 SQL*Net roundtrips to/from client 1 sorts (memory) 0 sorts (disk) 17 rows processed
x$kttets
有关这张系统表的相关信息很少SQL> desc x$kttets; 名称 是否为空? 类型 ----------------------------------------- -------- ---------------------------- ADDR RAW(8) INDX NUMBER INST_ID NUMBER KTTETSTSN NUMBER KTTETSMSIZE NUMBER KTTETSSIZE NUMBER KTTETSUSED NUMBER KTTETSEMA NUMBER KTTETSCTIME NUMBER KTTETSCSCN NUMBER KTTETSLASTRFN NUMBER
v$filespace_usage
V$FILESPACE_USAGE summarizes space allocation information of each datafile and tempfile. —— [ Oracle在线文档 ]SQL> desc v$filespace_usage 名称 是否为空? 类型 ----------------------------------------- -------- ---------------------------- TABLESPACE_ID NUMBER RFNO NUMBER ALLOCATED_SPACE NUMBER FILE_SIZE NUMBER FILE_MAXSIZE NUMBER CHANGESCN_BASE NUMBER CHANGESCN_WRAP NUMBER FLAG NUMBER
根据定义这张视图包含了所有表空间的使用的具体情况,事实上也是如此,之前有些文章里面有关DBA_TABLESPACE_USAGE_METRICS的定义里,其信息都是从这张视图中取出来的。在我测试的oracle版本是11.2.0.3,基础表的信息是由
x$kttets统计的
对比了一下由
v$filespace_usage和
x$kttets统计出来的基础表的信息,从
x$kttets统计出的信息比
v$filespace_usage要准确得多,这里主要是因为ALLOCATED_SPACE字段并不是指的已使用的空间的缘故,但这里FILE_MAXSIZE字段是没有问题的
sys.WRH$_TABLESPACE_SPACE_USAGE
前面说过使用DBA_TABLESPACE_USAGE_METRICS查询表空间使用情况在99%的情况下没有问题,但有1%的情况有可能因为x$kttets表没有被触发更新,会导致基础表的信息不准确,这种情况是有可能发生的,我就不巧碰到此情况,这有可能是oraclebug,我试验了几次,在没有重现过此情况。
下面查询dba_tablespace_usage_metrics结果(block_size为8K)
select * from dba_tablespace_usage_metrics
TABLESPACE_NAME | USED_SPACE | TABLESPACE_SIZE | USED_PERCENT |
---|---|---|---|
DATABAK | 396538250 | 402669384 | 98.4773777 |
GZCDR | 96887456 | 2684354560 | 3.609339 |
GZUNIBPMN | 2856 | 67108832 | .004255774 |
Tablespace_name | Size | Used | Free | Max | Usage% | Usageofmax% |
---|---|---|---|---|---|---|
DATABAK | 3040.02GB | 3025.31GB | 14.71GB | 3232GB | 99.52 | 93.6 |
GZCDR | 1024GB | 739.19GB | 284.81GB | 20480GB | 72.19 | 3.61 |
GZUNIBPMN | 1003.52MB | 0MB | 1003.52MB | 512GB | 0 | 0 |
x$kttets只更新了新增了一个数据文件的数据,非常的奇怪,在此之前没发生过这种情况,一般来说在新增了数据文件后,
x$kttets也会跟着更新,但这次没有,我也不知道这张表是如何触发更新从何处取得数据,因为有关这张表的信息实在找不到。
就在我绝望之时,我发现了表WRH$_TABLESPACE_SPACE_USAGE
SQL> desc sys.WRH$_TABLESPACE_SPACE_USAGE 名称 是否为空? 类型 ----------------------------------------- -------- ---------------------------- DBID NOT NULL NUMBER SNAP_ID NUMBER TABLESPACE_ID NUMBER TABLESPACE_SIZE NUMBER TABLESPACE_MAXSIZE NUMBER TABLESPACE_USEDSIZE NUMBER RTIME VARCHAR2(25)
select * from sys.WRH$_TABLESPACE_SPACE_USAGE
执行完这条语句后我惊喜的发现这是一个有关系统表空间使用情况的快照表,每个整点都会有所有表空间的使用数据情况的更新,例如这样
select * from sys.WRH$_TABLESPACE_SPACE_USAGE where to_date(rtime,'MM/dd/yyyy hh24:mi:ss')>sysdate-1/24
或者
select * from sys.WRH$_TABLESPACE_SPACE_USAGE where snap_id=(select max(snap_id ) from sys.WRH$_TABLESPACE_SPACE_USAGE)
DBID | SNAP_ID | TABLESPACE_ID | TABLESPACE_SIZE | TABLESPACE_MAXSIZE | TABLESPACE_USEDSIZE | RTIME |
---|---|---|---|---|---|---|
2272203595 | 8208 | 6 | 398475082 | 423624502 | 396543370 | 02/05/2016 16:00:04 |
2272203595 | 8208 | 7 | 131072 | 67108832 | 3680 | 02/05/2016 16:00:04 |
2272203595 | 8208 | 8 | 134217728 | 2684354560 | 125680016 | 02/05/2016 16:00:04 |
TABLESPACE_ID与TABLESPACE_NAME的关联关系可以用sys.ts$来关联
保证快速及准确的查询表空间
有了上面的讨论,为了快速的查询表空间的使用情况,我们可以这样select tablespace_name, round(used_space*(select value from v$parameter where name='db_block_size')/power(2,30),2) USED_GB, round(tablespace_size*(select value from v$parameter where name='db_block_size')/power(2,30)) MAXSIZE_GB, round(used_percent,2) as "PCT%" from dba_tablespace_usage_metrics;
这个有99%的准确率,1%的情况是意外(也有可能是bug)
也可以这样
select t.name tablespace_name, round(s.tablespace_size*(select value from v$parameter where name='db_block_size')/power(2,30)) SIZE_GB, round(s.tablespace_maxsize*(select value from v$parameter where name='db_block_size')/power(2,30)) MAXSIZE_GB, round(s.tablespace_usedsize*(select value from v$parameter where name='db_block_size')/power(2,30),2) USED_GB, round((s.tablespace_usedsize/s.tablespace_maxsize)*100,2) as "PCT%" from sys.WRH$_TABLESPACE_SPACE_USAGE s, sys.ts$ t where s.snap_id=(select max(snap_id ) from sys.WRH$_TABLESPACE_SPACE_USAGE) and s.tablespace_id=t.ts#
这个数据可能是最新的,也可能不是,但在你最近1小时内没有新增数据文件的情况下,它一定是最快最准确的
相关文章推荐
- 基于 Red Hat 的发行版 Oracle Linux 正式发布Oracle Linux 7.1
- Oracle Containers for J2EE远程安全漏洞(CVE-2014-0413)
- Oracle 10g R2不能使用EM的问题
- 表空间操作
- PreparedStatement中in子句的处理
- VMware下RedHat4.8_64位安装Oracle 10g RAC--简略脚本
- oracle sql日期比较
- 基于 Red Hat 的发行版 Oracle Linux 正式发布Oracle Linux 7.1
- OS block size和Oracle block size,查找OS Blocksize的方法
- oracle中创建数据库和表空间的几点总结
- 数据库自动备份脚本
- oracle的nvl函数的使用介绍
- 解决oracle用户连接失败的解决方法
- oracle的一些tips技巧
- Oracle 下的开发日积月累
- Oracle存储过程之数据库中获取数据实例
- Windows下ORACLE 10g完全卸载的方法分析
- Oracle ODI 12c之Setting Up Simple CDC