reference partition 是子表复用父表分区定义的依赖式分区,需通过启用验证的外键绑定且外键列与父表分区键完全一致;普通分区则独立定义分区逻辑。
reference partition 是什么,和普通分区有什么区别
Reference Partition 不是独立的分区方式,而是让子表复用父表的分区定义,靠外键约束绑定。它不自己定义 PARTITION BY,而是通过 REFERENCES 关键字指向父表。关键前提是:子表必须有启用的、启用验证的(ENABLE VALIDATE)外键,且该外键只引用父表的分区键列(通常是主键或唯一键)。
- 外键列必须和父表分区键完全一致(类型、长度、是否为 NULL),否则建表直接报错
ORA-14650: reference partitioning is not supported for this type of foreign key - 父表必须是已分区表(比如
RANGE或LIST分区),且不能是HASH分区(Oracle 12c+ 支持 HASH 作为父表,但仍有严格限制) - 子表插入数据时,会自动路由到与父表记录相同的分区;删父表分区时,可加
CASCADE自动清理子表对应数据
怎么写 Reference Partition 的建表语句
核心就两点:父表先建好分区,子表在 FOREIGN KEY 定义后紧跟 REFERENCES 父表名,并确保外键列顺序、数量、类型和父表分区键严格对齐。
CREATE TABLE orders ( order_id NUMBER PRIMARY KEY, cust_id NUMBER, order_date DATE ) PARTITION BY RANGE (order_date) ( PARTITION p_2023 VALUES LESS THAN (DATE '2024-01-01'), PARTITION p_2024 VALUES LESS THAN (DATE '2025-01-01') ); <p>CREATE TABLE order_items ( item_id NUMBER PRIMARY KEY, order_id NUMBER, product_id NUMBER, qty NUMBER, CONSTRAINT fk_order_items_order_id FOREIGN KEY (order_id) REFERENCES orders(order_id) ) PARTITION BY REFERENCE (fk_order_items_order_id);</p>
-
PARTITION BY REFERENCE后面括号里必须是外键约束名,不是列名,也不是表名 - 外键约束必须是
ENABLE VALIDATE状态;如果建表时没显式写,Oracle 默认就是这个状态,但后期禁用再启用可能破坏引用分区逻辑 - 子表不能额外指定分区策略(比如不能再写
PARTITION BY RANGE),否则语法报错ORA-14035: invalid partitioning method for reference-partitioned table
为什么子表数据没进对应分区?常见掉坑点
最常遇到的现象是:父表某条记录在 p_2024 分区,但插入子表同 order_id 的数据后,查 SELECT * FROM order_items PARTITION (p_2024) 返回空——说明数据进了别的分区,甚至可能进 DEFAULT 分区(如果父表用了 INTERVAL + DEFAULT)。
- 父表分区键是
order_date,但外键引用的是order_id(主键),而order_id不是分区键 → 这种情况根本建不出 Reference Partition,建表就失败 - 父表用了
INTERVAL分区,但子表首次插入时,父表还没生成目标分区(比如插了个 2025 年订单,但p_2025尚未自动创建)→ 子表插入会报ORA-14400: inserted partition key does not map to any partition - 外键约束被手动
DISABLE过,即使后来ENABLE了,Reference Partition 关系也可能失效(需重建约束或整个子表)
Reference Partition 对查询和维护的影响
它不改变 SQL 写法,但影响执行计划和 DDL 操作粒度:
- 查询带
WHERE order_id = ?时,优化器能自动做分区裁剪(Partition Pruning),但前提是外键列出现在 WHERE 条件中,且统计信息准确 - 删除父表一个分区(
ALTER TABLE orders DROP PARTITION p_2023)时,若子表很大,操作会变慢——因为 Oracle 要检查并清理子表对应分区;加UPDATE GLOBAL INDEXes或CASCADE会进一步延长锁持有时间 - 不能对子表单独做
SPLIT/MERGE分区;所有分区变更必须通过父表驱动 - 如果父表转成复合分区(比如
RANGE-HASH),子表仍可用REFERENCE,但外键必须引用父表的最外层分区键(即 RANGE 列),不能是子分区键
Reference Partition 看似省事,实际把子表的分区控制权完全交给了父表和外键完整性。一旦外键松动、父表分区策略调整、或者跨库/跨 schema 引用,这条路就走不通了。真要分治,有时显式同步建相同分区策略,反而更可控。










