查用户表大小必须用user_segments而非user_tables,因后者仅存元数据;user_segments中segment_name需严格匹配(默认大写),且同一表可能有多个segment(如LOB)。
查用户表大小必须用
,不是
只存元数据(比如列名、状态),不记录空间占用。真正反映物理大小的是
——它对应磁盘上实际分配的段(segment)。误用
会导致查不到任何字节数,甚至报“no rows selected”。
关键点:
必须大写,且与表名完全一致(Oracle 默认转大写,但若建表时加了双引号定义小写名,则需按原样匹配)
同一个表可能有多个 segment(如带 LOB 列时,
和
会单独计)
查询前确保你有访问
的权限;普通用户默认可查,但若被显式收回
,则会报
示例(查当前用户下
表总大小):
和
权限差异直接影响结果范围
用
能看到所有用户的对象大小,但前提是已授予
或
角色。没权限时直接执行会报
,而不是返回空结果——这点容易误判为“没数据”。
常见错误场景:
开发连测试库用普通账号,却复制 DBA 脚本里的
查询,结果报错
误以为
是“所有用户+自己”,其实它只显示当前用户有权限访问的对象(比如被授予
的其他用户表),大小值也仅反映你能读到的部分
在 RAC 环境中,
默认只查当前实例,跨实例需加
或切到对应实例连接
安全做法:先确认角色
精确查某张表真实数据量,得用
返回的是分配空间(包括未使用的高水位线以上空间),而
能给出已使用字节数、行数估算、链式行比例等更贴近实际的数据。
注意限制:
oracle知识库
oracle知识库下载
下载
必须用 PL/SQL 块执行,不能直接 SELECT
需要
权限 on
(通常随
或
角色附带,但某些最小化安装可能未赋)
参数填当前用户名即可,填错(如小写或空格)会报
类似误导性错误
简化版调用(查当前用户下的
):
其中
和
是绑定变量,需在支持绑定的客户端(如 SQL*Plus、SQL Developer)中定义并打印。
查视图/索引/LOB 对象大小容易漏掉类型过滤
一张表的空间可能分散在多个 segment 类型里:
、
、
、
、
。如果只查
,会严重低估总占用。
实操建议:
先看全貌:
对含 CLOB/BLOB 的表,务必补查:
(系统生成的 LOB 段名有固定前缀)
物化视图日志(
)也会产生
类型 segment,但名字带
前缀,容易被忽略
最简汇总语句(含常见类型):
真实环境里,LOB 和索引常占表总大小的 30%–200%,跳过它们等于只看了冰山一角。
user_segmentsuser_tablesuser_tablesuser_segmentsuser_tablessegment_nameLOBSEGMENTLOBINDEXuser_segmentsSELECT_CATALOG_ROLEORA-00942: table or view does not existEMPLOYEESSELECT SUM(bytes) / 1024 / 1024 AS "size_mb"
FROM user_segments
WHERE segment_name = 'EMPLOYEES';dba_segmentsuser_segmentsdba_segmentsSELECT ANY DICTIONARYDBAORA-00942dba_segmentsall_segmentsSELECTdba_segments@dblinkSELECT granted_role FROM session_roles WHERE granted_role IN ('DBA', 'SELECT_ANY_DICTIONARY');dbms_space.object_space_usageuser_segments.bytesdbms_space.object_space_usageEXECUTEdbms_spaceCONNECTRESOURCEsegment_ownerORA-32034: unsupported use of WITH clauseORDERSBEGIN
dbms_space.object_space_usage(
segment_owner => USER,
segment_name => 'ORDERS',
segment_type => 'TABLE',
used_bytes => :used,
alloc_bytes => :alloc
);
END;:used:allocTABLEINDEXLOBSEGMENTLOBINDEXMATERIALIZED VIEWsegment_type = 'TABLE'SELECT segment_type, COUNT(*) FROM user_segments GROUP BY segment_type;WHERE segment_name LIKE 'SYS_LOB%' OR segment_name LIKE 'SYS_IL%'MVIEW LOGTABLERUPD$_SELECT segment_type, SUM(bytes)/1024/1024 AS mb
FROM user_segments
WHERE segment_name IN (
SELECT table_name FROM user_tables
UNION
SELECT index_name FROM user_indexes
UNION
SELECT segment_name FROM user_lobs
)
GROUP BY segment_type;