RANGE-HASH组合分区是先按范围(如时间、ID区间)主分区,再对每个主分区按哈希键子分区;适合数据有明显范围倾斜且单范围数据量极大、需打散避免IO热点的场景。

什么是范围哈希组合分区,它适合什么场景
Oracle 的 RANGE-HASH 组合分区是先按范围(如时间、ID 区间)切分大表,再对每个范围子分区做哈希子分区。它适合数据有明显时间/序列倾斜(比如按 order_date 分月),但单月数据量又极大、需进一步打散到多个段以避免热点和并行瓶颈的场景。
典型误用是:仅因“听说哈希能均衡”就对高基数列直接哈希分区——这会破坏范围查询的剪枝能力;或者对低基数范围列(如只有 3 个状态值)强行 RANGE-HASH,导致子分区数爆炸且无效。
建表时必须显式指定两级分区键和子分区模板
Oracle 不允许在建表语句里省略子分区定义。你必须同时声明主分区键(RANGE)和子分区键(HASH),且子分区键必须是主分区键的**超集**(即包含所有主分区键列,可多不可少)。
-
CREATE TABLE t (id NUMBER, dt DATE, val VARCHAR2(10)) PARTITION BY RANGE(dt) SUBPARTITION BY HASH(id) SUBPARTITIONS 4✅ 合法:子分区键id是独立列,且主分区键dt未被要求参与哈希 -
PARTITION BY RANGE(dt) SUBPARTITION BY HASH(dt)❌ 报错ORA-14039:范围列不能单独作为哈希子分区键 -
SUBPARTITION BY HASH(id, dt)✅ 允许,但哈希计算只基于id和dt的组合值,实际效果可能偏离预期,慎用
范围边界定义不当会导致子分区数量失控
每个范围分区下的子分区数量 = 指定的 SUBPARTITIONS N 值,不是全局总数。如果定义了 12 个按月的范围分区,又设 SUBPARTITIONS 8,最终物理段数就是 12 × 8 = 96 —— 这会显著增加段管理开销、影响 DDL 性能,甚至触发 ORA-14221(子分区数超限)。
实操建议:
- 优先用
STORE IN (tbs1, tbs2, ...)控制子分区分布,而非盲目增加SUBPARTITIONS - 范围分区数量宜控制在 10–30 个以内;子分区数建议 2–8,视并发写入压力和 CPU 核心数而定
- 避免用
MAXVALUE作为唯一上限分区,否则后续无法自动分裂,需手工ALTER TABLE ... SPLIT PARTITION
查询性能依赖谓词是否覆盖两级分区键
Oracle 只有在 WHERE 条件同时满足范围剪枝(如 dt BETWEEN '2025-01-01' AND '2025-01-31')且哈希键参与等值过滤(如 id = 12345)时,才能定位到唯一子分区。否则只能扫描整个范围分区下的全部子分区。
常见陷阱:
- 仅用
WHERE id = 12345→ 全表扫描所有范围分区的所有子分区 - 仅用
WHERE dt > SYSDATE - 30→ 扫描匹配的范围分区,但每个分区内仍扫全部子分区 - 正确姿势:
WHERE dt = DATE '2025-01-15' AND id = 12345→ 精确命中单个子分区
如果业务查询天然缺少哈希键等值条件,RANGE-HASH 就失去了意义,此时 RANGE-LIST 或纯 RANGE 更合适。


















