无效。ALTER TABLE 修改 PCTFREE 仅更新元数据,不改变已有数据块的空闲空间;新值仅对后续插入、MOVE 或 REBUILD 后的新块生效,须配合物理重组(如 MOVE 或 DBMS_REDEFINITION)及索引重建才能真正减少行迁移。

直接 ALTER TABLE 修改 PCTFREE 有效吗?
无效。修改 PCTFREE 参数本身**不会立即影响已有数据块**,它只对后续新插入或迁移后的行生效。你执行 ALTER TABLE t PCTFREE 30 后,表里已存在的块仍按旧的 PCTFREE(比如默认10)组织;只有新分配的块、或经过 MOVE/REBUILD 的块才会使用新值。
常见错误现象:改完就查 user_tables.pct_free 确实变了,但性能没改善、ANALYZE TABLE t VALIDATE STRUCTURE CASCADE 仍报大量行迁移 —— 这说明老块没重排。
- 必须配合物理重组操作才能让新
PCTFREE起作用 - 如果表空间启用了 ASSM(
segment_space_management = 'AUTO'),PCTUSED被忽略,只看PCTFREE - 确认是否 ASSM:
SELECT tablespace_name, segment_space_management FROM user_tablespaces
什么时候该调高 PCTFREE?关键看更新行为
PCTFREE 是为 UPDATE 预留空间的“安全垫”。设得太低(如默认10),频繁更新变长字段(如 VARCHAR2 扩容、UPDATE ... SET desc = desc || 'xxx')会快速填满块,触发行迁移;设太高(如50)则浪费磁盘和缓存,降低 I/O 效率。
判断依据不是“有没有 UPDATE”,而是:
- 平均行长度增长幅度:查
dba_tab_statistics.avg_row_len和业务逻辑预估更新后长度 - 更新频率与并发度:高并发 UPDATE 同一块易争用
ITL插槽,此时还需同步调高INITRANS - 典型场景:日志表(几乎只 INSERT)→
PCTFREE 5;用户资料表(常改地址/昵称)→PCTFREE 25–35
真正生效的三步操作链
光改参数没用,必须走完“声明 → 搬运 → 重建”闭环:
- 第一步:声明新预留值
ALTER TABLE orders PCTFREE 30; - 第二步:搬运数据到新块(触发重排)
ALTER TABLE orders MOVE TABLESPACE users;
注意:MOVE 期间表不可 DML,需维护窗口;若不能停写,改用DBMS_REDEFINITION - 第三步:重建所有索引(否则索引仍指向旧 ROWID)
ALTER INDEX orders_pk REBUILD ONLINE;ALTER INDEX orders_n1 REBUILD ONLINE;
遗漏第三步会导致查询走索引时反复跳转,反而放大性能问题。
在线重定义 vs MOVE:选哪个?
核心区别在业务连续性要求:
-
MOVE快、简单、资源消耗低,但锁表;适合夜间维护或小表 -
DBMS_REDEFINITION支持全程在线,但步骤多、临时空间大、需额外校验;适合核心大表(如千万级以上) - 别忽略隐含成本:MOVE 后索引失效需重建;在线重定义需同步物化视图日志、处理约束/触发器等边缘情况
最容易被忽略的是:无论哪种方式,**统计信息必须手动收集**,否则优化器仍按旧分布估算执行计划。EXEC DBMS_STATS.GATHER_TABLE_STATS('SCOTT','ORDERS');











