ALTER TABLE … MOVE PARTITION 是全量物理迁移,非元数据操作;会致本地索引失效、需重建,全局索引默认失效;须检查表空间空间、分区实际占用及索引状态,并注意 SATA 表空间需调优参数。
ALTER TABLE … MOVE PARTITION 会重建整个分区数据
这个操作不是简单改个元数据指针,而是把分区里所有行读出来、按新表空间的存储参数重新写一遍。实际就是一次全量物理迁移,io 和锁开销都很大。
常见错误现象:ORA-01652(无法扩展临时段)频繁出现,因为排序和重建过程大量依赖 TEMP 表空间;或者迁移中途被 kill,分区处于不可用状态。
- 必须确保目标表空间(比如
ARCHIVE_TBS)已存在,且有足够空闲空间 —— 建议预留至少 1.5 倍原分区大小 - 迁移期间该分区不可 DML(
INSERT/UPDATE/DELETE),但其他分区不受影响 - 如果表上有本地索引(
LOCAL INDEX),MOVE PARTITION后索引会自动变为UNUSABLE,必须立刻重建:ALTER INDEX idx_name REBUILD PARTITION p_old; - 全局索引(
GLOBAL INDEX)默认会失效,加UPDATE GLOBAL INDEXES子句可避免,但会显著拖慢执行时间
如何确认分区当前所在表空间及大小
别凭记忆或 DBA 邮件判断,直接查数据字典最准。尤其要注意:一个表的不同分区可能已在不同表空间,归档前必须逐个核对。
常用查询:
SELECT partition_name, tablespace_name, bytes/1024/1024 AS mb FROM dba_segments WHERE segment_name = 'YOUR_TABLE_NAME' AND segment_type = 'TABLE PARTITION' ORDER BY partition_name;
-
dba_segments查的是已分配空间,dba_tab_partitions查的是逻辑定义(比如tablespace_name默认值),两者不一致时以dba_segments为准 - 如果某分区返回空行,说明它还没被插入过数据,也未分配区(extents),此时
MOVE会报错ORA-14257 - 对超大分区(>100GB),建议先用
DBMS_SPACE.SPACE_USAGE估算实际占用,避免误判空闲空间
MOVE PARTITION 后索引和约束的状态变化
这是最容易翻车的地方 —— 表能查了,应用却报错,八成是索引没跟上。
本地索引分区在 MOVE 后立即变成 UNUSABLE,但不会报错;查询走不到它,优化器直接跳过,性能断崖下跌。
- 检查索引状态:
SELECT index_name, status, partition_name FROM dba_ind_partitions WHERE index_name = 'IDX_NAME'; - 重建单个分区索引:
ALTER INDEX idx_name REBUILD PARTITION p_2022q1; - 外键约束不受影响,但主键如果是本地分区索引,同样要重建 —— 否则
INSERT可能违反唯一性而不报错 - 不要用
REBUILD UNUSABLE INDEXES批量操作,容易误伤正在使用的索引分区
归档到 SATA 磁盘前的表空间配置要点
廉价 SATA 盘吞吐低、随机 I/O 差,不能照搬 SSD 表空间的参数,否则迁移慢、运行也慢。
关键差异点:
- 关闭
LOGGING(除非业务要求强一致性):ALTER TABLESPACE archive_tbs NOLOGGING;—— 能提速 3–5 倍,但意味着该表空间内操作无法通过归档日志恢复 -
INITIAL和NEXT区大小设大些(如 64M),减少区分配次数;PCTINCREASE设为 0,避免小碎片 - 禁用自动段空间管理(ASSM)?不推荐。SATA 盘更需要 ASSM 减少争用,但要把
BITMAP段预分配够,避免运行时频繁扩展 - 务必设置
DEFERRED_SEGMENT_CREATION=FALSE,否则新建分区可能不立即分配空间,后续MOVE会失败
真正麻烦的从来不是命令敲得对不对,而是迁移后没人去验证索引是否可用、统计信息是否更新、应用 SQL 执行计划有没有突变 —— 这些都得手动盯。










