您的位置:首页 > 数据库 > Oracle

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_NAMEUSED_SPACETABLESPACE_SIZEUSED_PERCENT
DATABAK39653825040266938498.4773777
GZCDR9688745626843545603.609339
GZ
e4d9
UNIBPMN
285667108832.004255774
这里used_space和tablespace_size的单位都是block

统计结果跟传统的方法在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_NAMEUSED_SPACETABLESPACE_SIZEUSED_PERCENT
DATABAK39653825040266938498.4773777
GZCDR9688745626843545603.609339
GZUNIBPMN285667108832.004255774
这是传统查询出来的结果

Tablespace_nameSizeUsedFreeMaxUsage%Usageofmax%
DATABAK3040.02GB3025.31GB14.71GB3232GB99.5293.6
GZCDR1024GB739.19GB284.81GB20480GB72.193.61
GZUNIBPMN1003.52MB0MB1003.52MB512GB00
两者并不一致,我在查询之前给DATABAK添加了3个自增长的数据文件,但
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)


DBIDSNAP_IDTABLESPACE_IDTABLESPACE_SIZETABLESPACE_MAXSIZETABLESPACE_USEDSIZERTIME
22722035958208639847508242362450239654337002/05/2016 16:00:04
22722035958208713107267108832368002/05/2016 16:00:04
227220359582088134217728268435456012568001602/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小时内没有新增数据文件的情况下,它一定是最快最准确的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息