chunk是lob读写的最小物理单位,不可修改,决定最小分配粒度;默认等于db_block_size(如8192字节),basicfile下设错将导致空间浪费与碎片不可回收,securefile可优化复用但不改变其基本约束。

CHUNK 是 LOB 数据读写的最小单位,不是可调的“压缩比”
CHUNK 决定了每次读写 LOB 时 Oracle 分配或访问的最小物理块大小,默认等于数据库块大小(通常是 8192 字节)。它不控制存储效率本身,但直接决定“哪怕只存 100 字节,也得占一个 CHUNK”的硬约束。这不是 bug,而是设计机制:LOB 数据按 CHUNK 对齐存储,无法跨 CHUNK 拆分小数据。
- CHUNK 太大(如默认
8192)→ 小文本、日志片段、JSON 片段等高频小写入场景下,空间浪费率飙升(100 字节占用 8KB = 99% 浪费) - CHUNK 太小(如设为
512)→ 增加 LOBINDEX 的条目数量和管理开销,可能拖慢随机访问性能,且不能低于数据库块大小的 1/2(否则建表报错ORA-43853) - CHUNK 一旦在建表时指定,后续无法用
ALTER TABLE修改,必须重建表+LOB 段才能调整
BasicFile LOB 下 CHUNK 设置错误会导致碎片不可回收
在 SECUREFILE=NO(即传统 BasicFile)模式下,CHUNK 不仅影响初始分配,还深度绑定空间复用逻辑。频繁 DBMS_LOB.WRITEAPPEND 追加小数据时,Oracle 会为每次追加分配新 CHUNK,而旧 CHUNK 即使只剩几十字节未用,也不会被合并或重用——因为 BasicFile 没有动态 CHUNK 合并机制。
- 现象:
SELECT SUM(bytes)/1024/1024 FROM dba_segments WHERE segment_name LIKE 'SYS_LOB%' AND owner = 'SCOTT'显示数百 MB,但实际 CLOB 总内容不到 10MB - 根本原因:大量低利用率 CHUNK 堆积,且因 BasicFile 的延迟回收机制,这些块需等待
undo_retention超时 + 无活跃读一致性需求,才可能被后台进程标记为可复用 - 注意:
TRUNCATE TABLE或DELETE对这些 CHUNK 段完全无效,它们仍钉在原位置
SecureFile LOB 可缓解但不消除 CHUNK 影响
SecureFile(SECUREFILE=YES)引入了智能 CHUNK 管理,比如自动压缩、重复数据删除、以及更积极的空闲 CHUNK 回收策略,但它仍以 CHUNK 为基本分配单元。也就是说,CHUNK 值依然决定单次最小分配量,只是后续空间复用能力更强。
- 新建 SecureFile 表时,CHUNK 仍需显式设置(如
CHUNK 2048),否则继承默认值;建议根据典型写入大小设为略大于该值(例如日志平均 1.2KB → 设CHUNK 2048) - SecureFile 允许运行时修改部分属性(如启用压缩),但
CHUNK仍是只读参数,改不了 - 若已有 BasicFile 表想换 CHUNK,唯一路径是导出数据 → 新建 SecureFile 表(带合适 CHUNK)→ 导入,过程中
DBMS_LOB.COPY会按新 CHUNK 重新组织物理存储
查当前 LOB 的 CHUNK 大小不能只看表定义
很多人用 DESC table_name 或查 USER_TAB_COLUMNS 找不到 CHUNK 值,因为它存在 USER_LOBS 视图里,且建表时若没显式指定,就取数据库默认块大小。
- 正确查询方式:
SELECT column_name, chunk, pctversion, cache FROM user_lobs WHERE table_name = 'TBL_X' - 如果
chunk返回0,说明建表时用了默认值(即db_block_size),此时需查SELECT value FROM v$parameter WHERE name = 'db_block_size' - 误判风险:开发说“我们设了 CHUNK 1024”,但 DBA 查
USER_LOBS发现是8192→ 实际是建表语句漏写了LOB (col) STORE AS (CHUNK 1024)子句,Oracle 自动回退到默认
free() 的 LOB locator 死死卡住旧块。











