Oracle表删除大量数据后,DBMS_SPACE查询可用空间返回空值的问题
解决表可用空间查询问题
首先纠正你操作中的错误:你在PL/SQL块里定义的变量是unused_blocks和unused_bytes,但执行print时查询的是未定义的FREE_BLOCKS,所以返回空值。正确的做法是执行:
print unused_blocks unused_bytes total_blocks total_bytes
这样就能看到DBMS_SPACE.UNUSED_SPACE返回的未使用块和字节数。
如果需要其他查询方式,可参考以下几种:
方式1:查询数据字典视图估算
通过USER_TABLES(当前用户)或DBA_TABLES(需权限)视图,结合行数据估算已分配但空闲的空间:
SELECT table_name, blocks AS 总分配块数, empty_blocks AS 未分配块数, ROUND((blocks - (num_rows * avg_row_len) / (8192 - 23)) * 8192 / 1024 / 1024, 2) AS 已分配空闲空间_GB FROM user_tables WHERE table_name = 'LOGIN_LOG';
注:公式中8192为默认数据块大小(若你的块大小不同需替换),23为块头占用的字节数,结果为估算值,仅供参考。
方式2:使用DBMS_SPACE.SPACE_USAGE(适用于ASSM表空间)
如果表所在表空间是自动段空间管理(ASSM)模式,可调用该存储过程直接获取未使用空间:
SET SERVEROUTPUT ON; DECLARE v_unused_bytes NUMBER; BEGIN DBMS_SPACE.SPACE_USAGE( segment_owner => 'CUSTOMER', segment_name => 'LOGIN_LOG', segment_type => 'TABLE', unused_space => v_unused_bytes ); DBMS_OUTPUT.PUT_LINE('未使用空间(字节): ' || v_unused_bytes); DBMS_OUTPUT.PUT_LINE('未使用空间(GB): ' || ROUND(v_unused_bytes / 1024 / 1024 / 1024, 2)); END; /
方式3:通过段和扩展区视图计算
结合DBA_SEGMENTS和DBA_EXTENTS统计总分配空间与已使用空间的差值:
SELECT s.segment_name, ROUND(s.bytes / 1024 / 1024 / 1024, 2) AS 总分配空间_GB, ROUND(SUM(e.bytes) / 1024 / 1024 / 1024, 2) AS 已使用空间_GB, ROUND((s.bytes - SUM(e.bytes)) / 1024 / 1024 / 1024, 2) AS 空闲空间_GB FROM dba_segments s JOIN dba_extents e ON s.owner = e.owner AND s.segment_name = e.segment_name AND s.segment_type = e.segment_type WHERE s.owner = 'CUSTOMER' AND s.segment_name = 'LOGIN_LOG' AND s.segment_type = 'TABLE' GROUP BY s.segment_name, s.bytes;
另外需要注意:删除大量数据后,释放的空间默认仅对当前表的新插入数据可用,不会立即归还表空间。若需将空间归还表空间,可执行ALTER TABLE LOGIN_LOG ENABLE ROW MOVEMENT;后再执行ALTER TABLE LOGIN_LOG SHRINK SPACE;,或使用ALTER TABLE LOGIN_LOG MOVE;(需重建索引)。
内容的提问来源于stack exchange,提问作者Landon Statis
相关产品推荐
相关产品推荐

