oracle 19c仅支持securefile lob列内字节级完全相同的blob/clob值原生去重,需建表时指定deduplicate且依赖assm表空间,basicfile不支持,后续无法启用,去重效果受限于数据重复度与操作方式。
oracle 19c 不支持 lob 列的原生去重(deduplication)功能。所谓“lob 去重”是常见误解,实际可用的是 deduplicate 子句,但它仅适用于 blob 和 clob 类型的 securefile lob,且去重发生在同一列内重复值之间,不是跨表或跨列的全局去重;普通 basicfile lob 完全不支持该特性。
确认是否启用 SecureFile 并检查存储类型
LOB 去重的前提是使用 SecureFile 存储。BasicFile 是 Oracle 11g 之前的默认格式,19c 中新建表若未显式指定,仍可能回退为 BasicFile(尤其在兼容性参数影响下)。
- 查当前 LOB 列是否为 SecureFile:
SELECT table_name, column_name, securefile FROM dba_lobs WHERE owner = 'YOUR_SCHEMA' AND segment_name = 'YOUR_LOB_SEGMENT'; - 返回
YES才可继续;若为NO,需重建 LOB 列(无法在线修改) - 确认表空间是否启用了 Automatic Segment Space Management(ASSM):SecureFile 强制要求 ASSM,否则建表报错
ORA-43853
创建支持 DEDUPLICATE 的 SecureFile LOB 列
必须在建表或添加 LOB 列时就指定 DEDUPLICATE,后续无法通过 ALTER TABLE ... MODIFY LOB 启用(会报 ORA-43856)。
- 新建表示例:
CREATE TABLE docs (id NUMBER, content CLOB) LOB(content) STORE AS SECUREFILE (DEDUPLICATE); - 若已有表需启用,只能导出数据 → 新建带
DEDUPLICATE的表 → 导入 → 重建索引/约束 - 注意:
DEDUPLICATE隐含启用COMPRESS HIGH,且不可单独关闭;如需去重但不压缩,目前无官方支持
去重生效条件与常见失效场景
即使声明了 DEDUPLICATE,实际去重也受严格限制,极易“看似配置成功却无效果”。
- 只对完全相同的 LOB 值去重(字节级一致),大小写、空格、换行符差异均视为不同值
- 只在同一 LOB 列内去重,跨列(如两个 CLOB 列)、跨表、跨分区均不共享去重块
- INSERT 时不会立即去重:首次插入相同值会生成新块;第二次插入相同时才复用已有块(需事务提交后才可见)
- UPDATE 某行 LOB 值为已存在值,会触发去重;但 UPDATE 为新值后又 UPDATE 回旧值,不一定复用(取决于内部块管理策略)
- 导出导入(EXPDP)默认不保留去重关系,还原后所有 LOB 变为独立副本
验证去重是否真实生效
不能只看表空间使用率下降——那可能是压缩或其它因素导致。要确认去重,必须查底层段结构。
- 查 LOB 段物理块数:
SELECT segment_name, bytes, blocks FROM dba_segments WHERE segment_name IN (SELECT segment_name FROM dba_lobs WHERE table_name = 'DOCS'); - 对比相同内容插入前后的
blocks增长量:插入 100 行相同 1MB CLOB,若启用DEDUPLICATE,blocks应只增约 128(1MB / 8KB),而非 12800 - 查去重统计(需启用跟踪):
SELECT * FROM v$securefile_sharing WHERE owner = 'YOUR_SCHEMA' AND table_name = 'DOCS';—— 此视图仅在发生去重后有记录
真正影响空间节省的,往往是 COMPRESS HIGH 而非 DEDUPLICATE;去重只在大量完全重复的大 LOB 场景下才有明显收益,比如文档库中反复上传同一份 PDF。多数业务数据的 LOB 值天然离散,配置了也几乎不生效——这点最容易被忽略。











