Oracle LOB段空间占用过多,如何通过ALTER TABLE MOVE操作优化清理?
- 内容介绍
- 文章标签
- 相关推荐
本文共计737个文字,预计阅读时间需要3分钟。
请提供需要改写的原文,我将按照您的要求进行改写。
lob段空间不会因delete或truncate自动释放,必须执行alter table ... move并显式指定lob子句,否则lob段原地不动。
为什么DELETE后空间不释放?
Oracle中LOB数据删除后,空间不会立即归还给表空间,而是进入“延迟回收”状态,需等待undo_retention超时才可能复用。即使TRUNCATE TABLE,若LOB列存储在SECUREFILE=NO(即BasicFile)模式下,其对应SYS_LOB***$$段仍保留在原位置,物理空间不收缩。
- 普通表行删除 → 空间可快速复用
- LOB列删除 → 空间标记为“待回收”,但段头未重置,
dba_segments中大小不变 - 现象:查
dba_segments发现SYS_LOB0000136091C00003$$仍占255GB,但表里已无数据
MOVE操作必须带LOB子句,否则无效
只写ALTER TABLE t MOVE,表段会迁移,但LOB段仍卡在原表空间、原位置,完全不移动——这是最常踩的坑。
- 正确语法必须包含
LOB (col_name) STORE AS ...子句 - 目标表空间须为ASSM(
SEGMENT SPACE MANAGEMENT AUTO),否则报ORA-43853 - 若要启用压缩/去重,只能在MOVE时指定,
MODIFY LOB不支持COMPRESS等属性 - 示例(安全写法):
ALTER TABLE your_schema.your_table MOVE TABLESPACE ts_lob_new LOB (content) STORE AS SECUREFILE ( TABLESPACE ts_lob_new COMPRESS HIGH DEDUPLICATE );
MOVE后索引失效,必须重建
MOVE是物理重组,所有基于原ROWID的索引(包括主键、唯一约束生成的索引)全部失效,状态变为UNUSABLE,查询会报错ORA-01502。
- 必须逐个重建:
ALTER INDEX idx_name REBUILD ONLINE; - 分区表需对每个分区索引单独处理,或使用
UPDATE GLOBAL INDEXES(仅限某些版本+语法) - 如忘记重建,应用执行
SELECT ... WHERE pk = ?可能直接失败,而非缓慢 - 重建期间索引不可用,建议安排在低峰期,加
ONLINE减少锁影响
确认LOB类型再动手,BasicFile才值得MOVE
不是所有LOB都适合MOVE重构。先查dba_lobs确认securefile字段值:
-
YES→ 已是SecureFile,MOVE收益有限(除非想换表空间或调参),优先考虑SHRINK SPACE(需行移动开启) -
NO→ BasicFile,MOVE + SECUREFILE是当前最有效手段 - 空值或查不到记录 → 该LOB列启用
STORAGE IN ROW,数据内联在表块中,不产生独立SYS_LOB***$$段,无需MOVE - 验证命令:
SELECT table_name, column_name, securefile FROM dba_lobs WHERE owner = 'YOUR_SCHEMA' AND table_name = 'YOUR_TABLE';
真正耗时的不是MOVE本身,而是判断是否该动、在哪动、动完怎么收场——尤其当LOB段跨多个表空间、或依赖物(物化视图、DBLink)未被识别时,容易引发连锁失效。
本文共计737个文字,预计阅读时间需要3分钟。
请提供需要改写的原文,我将按照您的要求进行改写。
lob段空间不会因delete或truncate自动释放,必须执行alter table ... move并显式指定lob子句,否则lob段原地不动。
为什么DELETE后空间不释放?
Oracle中LOB数据删除后,空间不会立即归还给表空间,而是进入“延迟回收”状态,需等待undo_retention超时才可能复用。即使TRUNCATE TABLE,若LOB列存储在SECUREFILE=NO(即BasicFile)模式下,其对应SYS_LOB***$$段仍保留在原位置,物理空间不收缩。
- 普通表行删除 → 空间可快速复用
- LOB列删除 → 空间标记为“待回收”,但段头未重置,
dba_segments中大小不变 - 现象:查
dba_segments发现SYS_LOB0000136091C00003$$仍占255GB,但表里已无数据
MOVE操作必须带LOB子句,否则无效
只写ALTER TABLE t MOVE,表段会迁移,但LOB段仍卡在原表空间、原位置,完全不移动——这是最常踩的坑。
- 正确语法必须包含
LOB (col_name) STORE AS ...子句 - 目标表空间须为ASSM(
SEGMENT SPACE MANAGEMENT AUTO),否则报ORA-43853 - 若要启用压缩/去重,只能在MOVE时指定,
MODIFY LOB不支持COMPRESS等属性 - 示例(安全写法):
ALTER TABLE your_schema.your_table MOVE TABLESPACE ts_lob_new LOB (content) STORE AS SECUREFILE ( TABLESPACE ts_lob_new COMPRESS HIGH DEDUPLICATE );
MOVE后索引失效,必须重建
MOVE是物理重组,所有基于原ROWID的索引(包括主键、唯一约束生成的索引)全部失效,状态变为UNUSABLE,查询会报错ORA-01502。
- 必须逐个重建:
ALTER INDEX idx_name REBUILD ONLINE; - 分区表需对每个分区索引单独处理,或使用
UPDATE GLOBAL INDEXES(仅限某些版本+语法) - 如忘记重建,应用执行
SELECT ... WHERE pk = ?可能直接失败,而非缓慢 - 重建期间索引不可用,建议安排在低峰期,加
ONLINE减少锁影响
确认LOB类型再动手,BasicFile才值得MOVE
不是所有LOB都适合MOVE重构。先查dba_lobs确认securefile字段值:
-
YES→ 已是SecureFile,MOVE收益有限(除非想换表空间或调参),优先考虑SHRINK SPACE(需行移动开启) -
NO→ BasicFile,MOVE + SECUREFILE是当前最有效手段 - 空值或查不到记录 → 该LOB列启用
STORAGE IN ROW,数据内联在表块中,不产生独立SYS_LOB***$$段,无需MOVE - 验证命令:
SELECT table_name, column_name, securefile FROM dba_lobs WHERE owner = 'YOUR_SCHEMA' AND table_name = 'YOUR_TABLE';
真正耗时的不是MOVE本身,而是判断是否该动、在哪动、动完怎么收场——尤其当LOB段跨多个表空间、或依赖物(物化视图、DBLink)未被识别时,容易引发连锁失效。

