确认LOB段是否为真问题需先查dba_lobs确定表归属及securefile/in_row属性;BasicFile且in_row=NO才导致空间膨胀,MOVE必须带LOB子句并指定存储参数,否则无效。
怎么确认LOB段是不是真问题
别一看到DBA_SEGMENTS里有个SYS_LOB%段占几百GB就开干。先查它到底属于哪张表、是不是BasicFile:
SELECT table_name, column_name, securefile, in_row, segment_name FROM dba_lobs WHERE owner = 'YOUR_SCHEMA' AND segment_name = 'SYS_LOB0000136091C00003$$';
如果securefile = 'NO',且in_row = 'NO'(即数据存外段),这才是空间膨胀的主因;若securefile = 'YES',那问题大概率出在未清理的旧版本或未收缩的空间,MOVE收益有限。
MOVE操作必须带LOB子句,否则白跑一趟
只写ALTER TABLE t MOVE,表数据会挪走,但LOB段纹丝不动——这是线上最常踩的坑。真正生效的写法必须显式指定LOB列和目标存储参数:
ALTER TABLE your_schema.your_table MOVE TABLESPACE ts_lob_new LOB (content) STORE AS SECUREFILE (COMPRESS HIGH DEDUPLICATE);
注意三点:
- 目标表空间必须是SEGMENT SPACE MANAGEMENT AUTO(ASSM),否则报ORA-43853
- COMPRESS和DEDUPLICATE只对MOVE时迁移的数据生效,存量BasicFile数据不会被压缩或去重
- 如果表是分区表,得对每个分区单独加PARTITION p_name子句,不能只写表级MOVE
MOVE后索引全失效,不重建就查不了
MOVE是物理重组,所有基于原ROWID的索引(包括主键、唯一约束生成的索引)状态会变成UNUSABLE,后续查询直接报ORA-01502。必须逐个重建:
ALTER INDEX your_schema.pk_your_table REBUILD ONLINE;
但注意:
- LOB索引(SYS_IL%)不支持ONLINE重建,只能离线重建
- 分区表的本地索引需对每个分区单独处理,或用UPDATE GLOBAL INDEXES(仅限12c+且语法兼容)
- 重建期间索引不可用,建议在业务低峰执行,并提前检查V$SESSION是否有长时间阻塞
旧LOB段不会自动消失,得手动清理
MOVE完成后,原BasicFile对应的SYS_LOB%段仍躺在表空间里,DBA_SEGMENTS.BYTES照常显示占用,但实际已无数据指向它。清理前务必确认:
- 没有其他对象依赖该段:SELECT owner, object_name, object_type FROM dba_objects WHERE object_id = &old_object_id;
- 表上没开启FLASHBACK或LOGGING相关依赖(尤其归档场景)
清理命令就是DROP SEGMENT,但Oracle不提供直接DROP语句,只能通过TRUNCATE TABLE ... DROP STORAGE或导出-删除-导入方式释放空间;更稳妥的是等MOVE完成并验证新段可用后,再用PURGE RECYCLEBIN清空回收站——很多“空间没释放”其实是回收站里还卡着旧段。

















