Oracle多列组合分区分两类:一是多列范围分区,用(col1,col2)字典序比较元组边界,主键须包含全部分区列;二是组合分区,一级与二级分区键必须为不同列,子分区需穷举值且不能用DEFAULT。

Oracle 支持多列组合分区,但不是“多个分区键并列”,而是指在单一分区策略中使用多列作为分区键(如 RANGE 或 LIST),或在组合分区(PARTITION BY ... SUBPARTITION BY ...)中分别指定不同列。混淆这两者是常见错误源头。
多列范围分区:用 (col1, col2) 一起定义 RANGE 边界
当业务需要按多个维度联合切分(比如先按区域代码再按日期),可直接在 PARTITION BY RANGE 中声明多列。Oracle 按字典序比较元组值,不是分别判断每列。
-
VALUES LESS THAN (591, DATE'2019-02-01')表示:所有满足(area_code, deal_date) < (591, '2019-02-01')的行归入该分区——即area_code < 591,或area_code = 591 且 deal_date < '2019-02-01' - 必须为每个分区显式写出完整元组边界,不能省略前导列;漏写会导致
ORA-14020错误 - 查询时若
WHERE条件只含第二列(如仅deal_date > ...),无法触发分区剪枝,性能退化 - 主键必须包含全部分区列,否则建表报
ORA-14038
组合分区:一级和二级分区键必须是不同列
组合分区(如 RANGE-SUBPARTITION BY LIST)要求一级分区键和二级子分区键是**不同列**,不能复用同一列。这是语法硬性限制。
- 正确:
PARTITION BY RANGE(sale_day) SUBPARTITION BY LIST(start_city)—— 两列分离 - 错误:
PARTITION BY RANGE(dt) SUBPARTITION BY LIST(dt)—— Oracle 直接拒绝,报ORA-14036(partitioning key column not allowed in subpartitioning key) - 子分区数建议设为质数(如 3、7、11),避免哈希冲突集中;
SUBPARTITIONS 8在某些数据分布下反而加剧热点 - 子分区不能单独指定表空间,除非在每个一级分区内部显式列出所有子分区并绑定
TABLESPACE
LIST-LIST 组合分区需注意值枚举完整性
当一级用 LIST、二级也用 LIST 时,所有可能的二级键值必须被覆盖,否则插入未声明的值会报 ORA-14400(inserted partition key is outside specified partition)。
- 例如一级按
region分区,二级按status子分区,则每个region分区下的子分区VALUES必须穷举该 region 下所有合法status值 - 不能依赖“默认子分区”;
VALUES (DEFAULT)不被支持于子分区定义中 - 维护成本高:新增一种
status值,需手工为每个一级分区添加对应子分区
真正容易被忽略的是多列范围分区的边界语义——它不是“AND 条件叠加”,而是元组比较。写错边界值会导致数据错分且难以排查,尤其在跨年/跨区域场景下。调试时务必用 SELECT PARTITION_NAME FROM USER_TAB_PARTITIONS WHERE TABLE_NAME = 'xxx' 核对实际分区范围,别只看建表语句。


















