哈希分区数必须为2的N次方,否则报ORA-14020;Oracle 12c+强制要求PARTITIONS值为1、2、4、8、16等,因位运算hash_value & (n-1)仅在n为2的幂时等价于取模且无分布偏差。
哈希分区数必须是2的n次方,否则建表会报错 ora-14020。 这不是建议,是oracle 12c(含)之后的硬性要求——partitions n 中的 n 必须为 1、2、4、8、16、32、64 等 2 的整数次幂。低于 12c 的旧版本虽允许非 2 的幂(如 3、5、6),但 12c+ 已彻底禁止。
为什么 Oracle 强制要求 2 的 N 次方?
Oracle 内部哈希函数输出一个固定位宽的哈希值(例如 32 位),再通过位掩码(bitmask)快速定位分区,公式本质是:partition_index = hash_value & (n - 1)。这个运算仅在 n 是 2 的幂时才等价于取模(hash_value % n),且能用位运算替代除法,性能更高、无余数偏差。若强行用 6 分区,hash_value & 5 会把高位哈希空间“折叠”进低 3 位,导致分布严重倾斜——这不是理论风险,实测中 6 分区的实际数据量差异可达 3:1 以上。
选 8 还是 16?关键看数据量和并发写入压力
分区数不是越多越好,需平衡存储碎片与并发吞吐:
- 小于 1000 万行:选
PARTITIONS 4或8足够;太多分区会让每个分区太小,INITIALextent 浪费明显,且 DML 并发争用 LATCH 的概率反而上升 - 单表超 5000 万行或高并发 INSERT(如每秒千级):优先
PARTITIONS 16;可显著降低单个分区的 ITL(Interested Transaction List)争用和 buffer busy waits - 已存在大量重复分区键值(如
pro_num固定为 3 个值):即使设PARTITIONS 32,实际也只用到 3 个分区——哈希分区无法规避“键值离散度低”的本质缺陷,此时应改用列表分区或加盐(salting)处理
建表时漏写 PARTITIONS,会触发默认行为吗?
不会。Oracle 不提供隐式默认值:
- 显式写
PARTITION BY HASH(col) PARTITIONS 8→ 正常创建 8 个系统命名分区(SYS_P1~SYS_P8) - 只写
PARTITION BY HASH(col)(无PARTITIONS子句)→ 直接报错ORA-14021: missing PARTITIONS keyword - 误写
PARTITIONS 0或负数 → 报错ORA-14020: invalid value (0) for PARTITIONS
注意:PARTITIONS 后面不能跟括号列表(如 (PARTITION p1, PARTITION p2)),那是范围/列表分区的语法;哈希分区只接受纯数字,且必须是 2 的幂。
真正容易被忽略的是:哈希分区后,SELECT COUNT(*) FROM t 的执行计划里看不到分区裁剪(Partition Pruning),因为哈希值不可预测——你永远没法用 WHERE col = ? 让 Oracle 推导出唯一分区,它只能全分区扫描。这点和范围分区有本质区别,别被“分区”二字误导。











