alter table … move partition 是全量物理迁移,非元数据操作;会致本地索引失效、需重建,全局索引默认失效;须检查表空间空间、分区实际占用及索引状态,并注意 sata 表空间需调优参数。

直接结论:用 ALTER TABLE ... MOVE PARTITION 把单个分区挪到新表空间,不是改元数据,是物理重写整块数据——必须停该分区的 DML,且会触发本地索引失效、全局索引默认失效。
MOVE PARTITION 为什么不能只改表空间指针?
Oracle 的分区迁移不是逻辑切换。它会把原分区所有行读出、按新表空间的存储参数(如 PCTFREE、INITIAL)重新分配块、写入目标表空间。整个过程是全量 IO + 排序 + 锁表,临时段(TEMP)压力极大。
常见错误现象:ORA-01652(无法扩展临时段)高频出现;中途被 kill,分区进入不可用状态,查 dba_segments 会发现该分区记录消失或大小为 0。
- 必须确保目标表空间(比如
ARCHIVE_TBS)已存在,且空闲空间 ≥ 原分区已分配空间的 1.5 倍(dba_segments.bytes值) - 执行期间,该分区禁止
INSERT/UPDATE/DELETE;其他分区不受影响 - 别依赖
dba_tab_partitions.tablespace_name判断位置——它只是定义默认值;以dba_segments查询结果为准
如何确认目标分区当前实际所在表空间和大小?
别凭印象或脚本输出猜。一个表的不同分区可能早已散落在多个表空间里,归档前必须逐个核对。
执行这条语句:
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;
如果某分区在结果里没出现,说明它还没插入过数据、也没分配 extent,此时执行 MOVE PARTITION 会报 ORA-14257(分区不存在)。超大分区(>100GB)建议先跑 DBMS_SPACE.SPACE_USAGE 估算真实占用,避免误判空间余量。
MOVE 后索引为什么查不到、DML 却不报错?
这是最常翻车的点:表能 SELECT,但应用慢得离谱或唯一约束突然失效,八成是索引状态没处理。
- 本地索引(
LOCAL INDEX)在MOVE PARTITION后立即变成UNUSABLE,但 SQL 不报错,优化器直接跳过它——相当于“隐形失效” - 检查状态:
SELECT index_name, status, partition_name FROM dba_ind_partitions WHERE index_name = 'IDX_NAME'; - 重建单个分区索引:
ALTER INDEX idx_name REBUILD PARTITION p_2023q4; - 全局索引默认失效;加
UPDATE GLOBAL INDEXES子句可保持有效,但执行时间会显著拉长(尤其大表),慎用 - 主键若基于本地分区索引,同样要重建——否则
INSERT可能违反唯一性却不报错
为什么迁移完很快又空间不足?
根本问题不在表空间总量,而在单个数据块内碎片。如果原分区长期经历大量 UPDATE 且 PCTFREE 设置过低(比如 5 或 0),MOVE 到新表空间后若仍沿用旧参数,几周内就会复发迁移或空间争用。
真正容易被忽略的是:MOVE 同时是修复行迁移(row migration)的机会。建议在 MOVE PARTITION 时显式指定更高 PCTFREE(如 20),并确认目标表空间启用了 ASSM(自动段空间管理)——否则手动调参意义有限。











