LOB段实际占用远超数据本身,因默认不压缩、不deduplicate,更新写新块且旧版本滞留;DELETE不释放空间,需MOVE+SECUREFILE+COMPRESS+DEDUPLICATE并重建索引。
lob段实际占用空间远超数据本身,不是统计错误,而是oracle的存储机制和使用方式共同导致的——它默认不压缩、不 deduplicate,且每次更新都写新块。
LOB段默认不启用压缩和去重
Oracle 11g 及以后版本支持 SECUREFILE LOB,但新建表时若未显式指定 COMPRESS HIGH 和 DEDUPLICATE,仍会沿用旧式 BASICFILE 行为(或虽为 SECUREFILE 但未开启优化)。这意味着:
- 相同内容的 CLOB 在不同行中重复存储,
ora_hash(dbms_lob.substr(clob_col, 4000, 1))聚合可暴露大量哈希碰撞 - 即使只改一行中一个字节,整个 LOB 块也会被复制到新位置,旧版本保留在段中,直到空间重用触发
-
COMPRESSION默认是NONE,DEDUPLICATION默认是DISABLE
LOB段空间无法随 DELETE 自动回收
删除含 LOB 的行,只是标记逻辑删除,LOB 段中的数据块不会立即释放。尤其在以下场景下更明显:
- 执行
DELETE FROM table WHERE ...后未做ALTER TABLE ... SHRINK SPACE CASCADE - LOB 存储在独立表空间,而该表空间未启用
AUTOEXTEND OFF或未设置合理MAXSIZE,导致文件持续膨胀但空闲块离散 - 回收站(
RECYCLEBIN)启用时,删掉的 LOB 段仍被保留,SHOW RECYCLEBIN可查到SYS_LOB*对象
LOB索引和 CHUNK 大小加剧空间浪费
每个 LOB 字段自动附带一个 LOBINDEX 段,它本身也占空间;同时 CHUNK 设置不当会放大碎片:
-
CHUNK是 LOB 数据读写的最小单位,默认为数据库块大小(通常 8KB),哪怕只存 100 字节,也会分配一个 CHUNK - 频繁小量追加(如日志类 CLOB 每次 append 一段)会导致大量低利用率 CHUNK
-
LOBINDEX段随 LOB 数据增长而线性膨胀,且无法用ALTER INDEX REBUILD单独收缩,必须配合MOVE或SHRINK
导出导入过程可能放大空间占用
使用 expdp/impdp 时,若未指定 TRANSFORM=SEGMENT_ATTRIBUTES:n 或未在目标端重建 LOB 属性,会继承源端低效设置:
- 源库用
COMPRESS LOW,导入后变成NONE(取决于 Data Pump 版本与兼容性) - 导入时默认创建新段,不复用原空闲空间,且
STORAGE参数可能按最大预估分配 - 测试发现:同一张含 CLOB 表,源库占 2.13MB,导入后达 170MB,根源就在
dba_lobs.compression从HI变成NO
真正要收窄 LOB 空间,不能只看 dba_tables.blocks,得进 dba_segments 拆解表段、LOB段、LOBINDEX 段三者各自占比;而修复动作本身(如 MOVE ... STORE AS SECUREFILE COMPRESS HIGH DEDUPLICATE)会锁表、使索引失效,必须安排停机窗口——这点容易被忽略,但恰恰是生产环境最卡脖子的地方。


















