哈希分区数必须是2的幂,否则建表直接报错;oracle 12c+强制要求partitions后为1、2、4、8等2的整数次幂,非2的幂如6或12触发ora-14020错误;底层依赖hash_value & (n-1)位运算,仅当n为2的幂时等价于取模,否则导致数据倾斜。

哈希分区数必须是2的幂,否则建表直接报错
Oracle 12c 及以上版本强制要求 PARTITIONS 后跟的数字只能是 1、2、4、8、16、32、64 等 2 的整数次幂。写 PARTITIONS 6 或 PARTITIONS 12 会立刻触发 ORA-14020 错误,根本无法建表。这不是兼容性警告,而是语法级硬限制。
原因在于 Oracle 内部用 hash_value & (n - 1) 替代取模运算——这个位与操作仅在 n 是 2 的幂时才等价于 hash_value % n。一旦违反,底层哈希映射逻辑失效,数据必然倾斜。
选 4、8 还是 16?看数据量和写入压力
分区数不是越多越好,关键要匹配实际负载:
- 单表行数 PARTITIONS 4 或
PARTITIONS 8足够;太多分区会让每个分区太小,INITIAL extent 浪费明显,且 DML 争用 latch 的概率反而升高 - 单表 > 5000 万行,或 INSERT 并发持续超每秒千级:优先选
PARTITIONS 16;能显著降低 ITL 争用和buffer busy waits - 分区键离散度极低(比如只有 3 个不同值):哪怕设
PARTITIONS 32,也只用到 3 个分区——此时哈希分区已失效,该换列表分区或加盐处理
建表时漏写 PARTITIONS,Oracle 不会帮你补默认值
PARTITION BY HASH (id) 单独写,不带 PARTITIONS 子句,Oracle 直接报错,不会默认给 1 个或 4 个分区。你必须显式写出数字,且只能是 2 的幂。
常见错误写法包括:
-
PARTITION BY HASH (id) (PARTITION p1, PARTITION p2)—— 这是列表/范围分区语法,哈希分区不支持括号列表 -
PARTITIONS 0或负数 —— 语法错误 - 依赖自动推导或“让 Oracle 自己决定”——它不会决定,只会拒绝执行
哈希分区后,WHERE id = ? 无法触发分区裁剪
这是最容易被忽略的语义陷阱:哈希分区的分区号由 hash(id) & (n-1) 算出,但 Oracle 无法在解析阶段反向推导出哪个分区包含某个具体 id 值。所以 SELECT * FROM t WHERE id = 123 仍需扫描全部分区,执行计划里看不到 partition pruning。
换句话说,哈希分区只解决 IO 均衡和热点分散,不解决查询过滤效率。如果业务大量依赖等值查询+精准定位,又指望分区裁剪加速,那哈希分区本身就不适配——该选范围或列表分区。











