跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何交换表分区_ALTER TABLE EXCHANGE PARTITION实现数据快速导入导出

EXCHANGE PARTITION能秒级导入导出数据,因其仅交换元数据而非移动实际数据文件;要求源表与目标分区结构完全一致,包括列定义、约束、索引等,否则直接报错。 EXCHANGE PARTITION 为什么能“秒级”导入导出数据 因为
exchange partition
不移动实际数据文件,只交换元数据(比如分区定义、段名、高水位等),本质是把两个表的物理存储“换个名字”。只要源表和目标分区结构完全一致(列名、顺序、类型、not null 约束、索引、约束等),就能跳过 insert/load 的逐行写入开销。 但这也意味着:一旦结构有细微差异,语句直接报错,不会静默兼容。 源表必须和目标分区所属表具有完全相同的列定义(包括隐式类型转换不被允许) 源表不能有主键或唯一索引(除非目标表也启用
INCLUDING INDEXES
,且索引结构匹配) 源表不能有外键引用,也不能被外键引用(否则需先禁用约束) 目标分区必须为空(
EXCHANGE
不会清空它,只做交换;若非空,需先
TRUNCATE PARTITION
) ORA-14097 错误:列顺序或类型不匹配的典型表现 执行
ALTER TABLE t EXCHANGE PARTITION p1 WITH TABLE t_staging
时抛出
ORA-14097: column type or size mismatch in ALTER TABLE EXCHANGE PARTITION
,大概率不是类型“看起来不同”,而是细节没对齐。 常见真实原因:
DATE
列和
TIMESTAMP
列互换 —— 即使都存时间,Oracle 视为不兼容 源表某列为
VARCHAR2(100)
,目标分区对应列为
VARCHAR2(100 CHAR)
或
VARCHAR2(100 BYTE)
—— 单位不显式声明时默认行为可能不一致 一列在源表为
NUMBER(10,2)
,另一列为
NUMBER
(无精度)—— Oracle 认为后者可容纳更大范围,但交换要求“完全一致” 源表含虚拟列,而目标分区表不含,或反之 查证方式:用
DBA_TAB_COLUMNS
对比两者的
DATA_TYPE
、
DATA_LENGTH
、
DATA_PRECISION
、
DATA_SCALE
、
CHAR_LENGTH
、
NULLABLE
字段,一个都不能差。 如何安全地准备 staging 表(避免反复建表失败) 别手写
CREATE TABLE
,容易漏掉约束或隐藏属性。最稳的方式是用目标表的 DDL 做基础,再删掉分区逻辑: 用
DBMS_METADATA.GET_DDL('TABLE', 'T')
获取原表完整 DDL 手动删掉
PARTITION BY ...
及所有
PARTITION
子句 删掉
ENABLE ROW MOVEMENT
(非必需,但 staging 表通常不需要) 确保
COMPRESS
、
SEGMENT CREATION
、
TABLESPACE
等物理属性与目标分区所在表空间一致(否则交换后可能触发隐式移动) 特别注意:staging 表的
TABLESPACE
必须和目标分区当前所在的表空间相同,否则
EXCHANGE
会失败(ORA-14157)。如果不确定,先查
DBA_TAB_PARTITIONS
的
TABLESPACE_NAME
字段。 EXCHANGE 后数据“消失”?其实是分区归属变了 执行成功后发现数据“不见了”,不是丢了,而是原来在
t_staging
里的数据,现在属于
t
的某个分区;而原来
t
分区里的数据,现在跑到了
t_staging
表里。 所以正确流程应该是: 导入新数据到
t_staging
(用
INSERT /*+ APPEND */
或
SQL*Loader DIRECT=TRUE
) 确认
t_staging
数据无误,且目标分区为空 执行
ALTER TABLE t EXCHANGE PARTITION p1 WITH TABLE t_staging
此时
t_staging
成了“空壳”,里面是原分区的老数据;真正的新数据已在
t
的
p1
中 如需复用
t_staging
,执行
TRUNCATE TABLE t_staging
清空老数据即可 最容易被忽略的是:交换后,
t_staging
的统计信息不会自动更新,后续如果误用它做查询计划估算,可能严重失真。记得手动
DBMS_STATS.GATHER_TABLE_STATS
。

相关文章