CHUNK是LOB段物理存储的最小分配单元,必须为DB_BLOCK_SIZE整数倍且≥DB_BLOCK_SIZE;它决定每次至少分配多少空间,而非读取大小,且创建后不可修改。
CHUNK大小决定了LOB数据的最小分配单元
oracle 11g中,chunk 是 lob 段(lobsegment)里物理存储的最小单位,默认为 db_block_size(通常 8kb)。它不是“每次读多少”,而是“每次分配至少多少”。哪怕只存 1 字节的 clob,只要 chunk 设为 8192,oracle 就会先分配一个完整 chunk —— 这个 chunk 内部可能只用到几个字节,其余空间闲置,且无法被其他 lob 或普通表数据复用。
-
CHUNK必须是DB_BLOCK_SIZE的整数倍,且 ≥DB_BLOCK_SIZE - 创建 LOB 时通过
CHUNK integer显式指定,例如:LOB (content) STORE AS (CHUNK 4096) - 一旦 LOB 段创建,
CHUNK大小不可修改(需重建 LOB 列) - 过大的
CHUNK(如 64KB)会导致大量内部碎片,尤其在平均 LOB 值远小于 CHUNK 时(比如存大量短文本或小图片)
小 CHUNK 不等于更省空间:要考虑块头和管理开销
直觉上把 CHUNK 设小(比如 1KB)能减少浪费,但实际会引入额外开销。每个 CHUNK 都需要 LOB index entry 和 segment header 管理信息;CHUNK 越小,相同数据量下 CHUNK 数量越多,索引条目膨胀,LOBINDEX 段本身也变大,甚至可能触发更多逻辑读。
- 实测场景:存平均长度 500 字节的 CLOB,
CHUNK=1024比CHUNK=8192总空间多出约 15–20%(含 LOBINDEX 增长) -
CHUNK小于DB_BLOCK_SIZE是非法的,会报错ORA-22295: cannot bind more than 4000 bytes to LOB(注意:此错误名易误导,实际常因 CHUNK 设置违反底层约束触发) - 对 BLOB 存二进制小文件(如图标、证书),建议
CHUNK设为略大于典型文件尺寸(如 2KB),而非盲目设小
如何查当前 LOB 的 CHUNK 设置和实际空间占用
不能只看 USER_LOBS 视图里的 CHUNK 列——它显示定义值,不反映真实空间效率。得结合段级统计和实际数据分布判断。
- 查定义:
SELECT column_name, chunk FROM user_lobs WHERE table_name = 'YOUR_TABLE'; - 查物理占用:
SELECT segment_name, bytes/1024/1024 AS mb FROM user_segments WHERE segment_name LIKE '%YOUR_LOB%'; - 估算浪费率:用
DBMS_SPACE.SPACE_USAGE获取 LOBSEGMENT 的unformatted_blocks和full_blocks,再比对平均 LOB 长度(AVG(LENGTH(lob_col)))与 CHUNK 比值
ALTER TABLE ... MODIFY LOB 不能改 CHUNK,只能重建
很多人误以为 ALTER TABLE t MODIFY LOB(c) (CHUNK 2048) 能在线调整,实际上 Oracle 11g 完全不支持该语法,会报 ORA-22858: invalid alteration of datatype。真要改 CHUNK,必须走重建路径,且有业务停机风险。
- 安全做法:新建列 → DBMS_LOB.COPY 迁移数据 → 重命名列 → 删除旧列
- 迁移时注意:若原 LOB 启用了
ENABLE STORAGE IN ROW,新列需显式指定,否则默认DISABLE,可能影响小 LOB 访问性能 - 重建后务必收集统计信息:
EXEC DBMS_STATS.GATHER_TABLE_STATS('SCHEMA','TABLE');,否则优化器仍按旧分布估算
ENABLE STORAGE IN ROW 设置、以及是否启用 COMPRESS 的组合效果。调优前,先用 LENGTH() 统计业务数据的真实尺寸分布——没这步,任何 CHUNK 调整都是拍脑袋。


















