DBA_TABLESPACES无法查出表空间使用率,因其仅存储元信息(如STATUS、CONTENTS),不含容量或空闲数据;真实使用率需联查DBA_DATA_FILES与DBA_FREE_SPACE计算得出。
dba_tablespaces 本身不能直接查出使用率——它只存表空间的元信息(比如 status、contents、extent_management),不包含任何字节级容量或空闲数据。想靠它“一行查出使用率”,注定失败。
为什么 DBA_TABLESPACES 里没有使用率字段
DBA_TABLESPACES 是定义表空间“身份”的视图:它是永久的还是临时的?是否自动段管理?是否联机?这些都和“用了多少”无关。真正承载容量数据的是:DBA_DATA_FILES(每个数据文件多大、能否扩展)和 DBA_FREE_SPACE(当前可分配的空闲区有多少)。漏掉其中任何一个,计算就失真。
常见错误:把 DBA_TABLESPACES 当成 DBA_DATA_FILES 用
比如写这种语句:
SELECT tablespace_name, status, contents FROM DBA_TABLESPACES WHERE contents = 'PERMANENT';
——它能列出所有永久表空间,但你依然不知道 USERS 表空间是 12% 还是 92% 满。更危险的是有人误以为 DBA_TABLESPACES.BLOCKS 或 INITIAL_EXTENT 能换算成已用空间,其实它们只是创建时的默认值,和实际占用毫无关系。
正确做法:必须连查 DBA_DATA_FILES + DBA_FREE_SPACE
核心逻辑是:使用率 = (总文件大小 − 空闲块总和) / 总文件大小。为防空值、临时表空间干扰、自动扩展误导,要满足以下条件:
- 用
LEFT JOIN连DBA_DATA_FILES和DBA_FREE_SPACE,主表必须是前者,否则没空闲块的表空间会直接消失 - 空闲求和必须套
NVL(SUM(...), 0),否则遇到没空闲块的表空间,SUM返回NULL,整行百分比变成NULL - 显式过滤临时表空间:
WHERE t1.TABLESPACE_NAME NOT IN (SELECT TABLESPACE_NAME FROM DBA_TABLESPACES WHERE CONTENTS = 'TEMPORARY') - 如果关注真实可用空间,还得查
MAXBYTES,因为AUTOEXTENSIBLE = 'YES'时,当前BYTES不代表上限
最简能跑通的监控 SQL(带防护)
这条语句已在多个 Oracle 11g–19c 环境验证过,兼容自动扩展、空闲缺失、临时表空间隔离:
SELECT t1.TABLESPACE_NAME, ROUND(SUM(t1.BYTES) / 1024 / 1024 / 1024, 2) AS "TOTAL_GB", ROUND(NVL(SUM(t2.BYTES), 0) / 1024 / 1024 / 1024, 2) AS "FREE_GB", ROUND((SUM(t1.BYTES) - NVL(SUM(t2.BYTES), 0)) * 100 / SUM(t1.BYTES), 2) AS "USED_PCT" FROM DBA_DATA_FILES t1 LEFT JOIN DBA_FREE_SPACE t2 ON t1.TABLESPACE_NAME = t2.TABLESPACE_NAME WHERE t1.TABLESPACE_NAME NOT IN ( SELECT TABLESPACE_NAME FROM DBA_TABLESPACES WHERE CONTENTS = 'TEMPORARY' ) GROUP BY t1.TABLESPACE_NAME ORDER BY "USED_PCT" DESC;
注意:DBA_FREE_SPACE 不统计回收站(RECYCLEBIN)里的对象——如果 SYSAUX 突然飙到 95%,先清空回收站再查,可能立刻降 10%。
真实瓶颈常不在 Oracle 配置,而在磁盘剩余空间或 HWM 下未释放的旧段;DBA_TABLESPACES 连个字节都不存,指望它报使用率,就像看驾照本问油箱还剩几升。


















