起作用,但只管数据块内空间预留,不管空闲块调度;PCTFREE控制块内预留空间供UPDATE扩展,ASSM下由位图块管理空闲块分配,PCTUSED完全失效,查询恒为NULL。
ASSM下PCTFREE还起作用吗?
起作用,但只管数据块内空间预留,不管空闲块调度。oracle 9i起默认启用自动段空间管理(assm),此时freelists和freelist_groups参数被完全忽略——哪怕你在建表时显式写了freelists 4,查询user_tables里这两列也永远是1。空闲块分配由位图块动态管理,而pctfree控制的是每个数据块内部“多少比例的空间留给后续update用”,它不参与跨块调度逻辑。
高并发INSERT时PCTFREE设多少才不卡住?
别死守默认10%,得看行长度变化率。如果字段经常从VARCHAR2(50) UPDATE成VARCHAR2(200),或含大量LOB索引键更新,建议把PCTFREE提到15~20%。否则ITL槽扩展失败、块内空间不足,会触发频繁的buffer busy waits和enq: TX - row lock contention。
- 估算公式:
PCTFREE ≈ (avg_row_len_after_update - initial_row_len) * 100 / avg_row_len_after_update - 实测发现:某日志表初始行长80字节,UPDATE后常达220字节,设
PCTFREE 20后db file sequential read下降37% - 注意:修改需重建段:
ALTER TABLE t MOVE PCTFREE 20 INITRANS 12,期间锁表
为什么PCTUSED在ASSM表空间里查不到?
因为ASSM根本不用PCTUSED。它靠位图块实时标记哪些块“可写入”,不再依赖传统PCTUSED阈值触发块重入free list。你执行SELECT table_name, pct_used FROM user_tables,结果恒为NULL——这不是查询错误,是设计如此。只要表空间启用了AUTO段管理(查dba_tablespaces.segment_space_management确认),PCTUSED就彻底失效,连建表时指定都会被忽略。
纯加载场景该不该用APPEND?
该,但必须配PCTFREE调优。直接路径插入(/*+ APPEND */)绕过位图块查找,从HWM上方连续分配新区,避免分散写入引发的物理读放大。但它对块内空间没要求,所以PCTFREE只影响后续常规INSERT和UPDATE;而APPEND写入的块默认按当前表定义的PCTFREE预留空间——如果这个值太小,后续第一条UPDATE就可能触发链式迁移。
- ETL加载前先执行:
ALTER TABLE log_table PCTFREE 15 - 加载SQL写成:
INSERT /*+ APPEND */ INTO log_table SELECT ... - 如允许无归档,加
NOLOGGING进一步提速,但记得之后立刻备份
真正容易被忽略的点是:PCTFREE调优必须结合INITRANS一起看。块内空间够了,但ITL槽只有默认2个,高并发下照样排队等TX锁。所以MOVE时务必同步设INITRANS,比如12或更高,且要确认表空间的block_size支持——8KB块最多容纳255个ITL槽,但受块头开销限制,实际建议不超过50。


















