应选高基数、访问分散的字段作分区键,如哈希后的order_id或created_at;避免低基数字段单独使用;必须用业务键时加ORA_HASH取模;优先用LOCAL索引而非GLOBAL索引。
分区键选什么才不加剧Cache Fusion争用
在多节点rac中,分区表若按业务主键(如user_id)分区,极易导致热点集中在少数节点——比如所有user_id为奇数的请求都落到node1,引发频繁的跨节点块传输。根本问题不在分区本身,而在分区键与访问模式耦合太紧。
- 优先选高基数、访问分散的字段,例如
order_id(全局唯一哈希后取模)或created_at(配合时间范围查询) - 避免用
tenant_id或region_code这类低基数字段单独作分区键,除非你确认每个租户/区域的数据量和访问频次高度均衡 - 如果必须用业务键,加一层哈希:用
MOD(ORA_HASH(user_id), 64)生成伪随机分区号,再结合RANGE或LIST分区策略落地
LOCAL索引为什么比GLOBAL更安全
GLOBAL INDEX在RAC下是单点瓶颈:任何DML修改都会触发跨节点的索引块争用,尤其在高并发插入场景,gc buffer busy acquire等待会飙升。而LOCAL INDEX天然绑定分区,每个节点只管自己的索引段。
- 新建分区表时,默认用
LOCAL,别图省事写GLOBAL - 已有
GLOBAL INDEX要改造?先评估索引列是否和分区键存在函数依赖,否则重建后可能无法裁剪分区 - 注意
LOCAL INDEX无法支持跨分区的唯一约束——如果需要全局唯一,得靠应用层或触发器兜底
如何验证数据真正在节点间打散了
光看DBA_TAB_PARTITIONS里的HIGH_VALUE没用,得查实际数据分布。RAC里最直接的证据是各节点的gc cr block received和gc current block received指标是否趋近平衡。
- 执行:
SELECT inst_id, COUNT(*) FROM your_table GROUP BY inst_id;—— 如果某节点结果占比超60%,说明打散失败 - 检查
V$PX_SESSION里并行查询是否均匀分配到各实例;若总看到INST_ID = 1占多数,大概率是分区键设计或并行度设置有问题 - 用
DBMS_ROWID.ROWID_BLOCK_NUMBER抽样一批ROWID,再查V$BH确认这些块是否分布在不同实例的buffer cache中
INSERT /*+ APPEND */对RAC分区表的隐性影响
APPEND直通路径写入虽快,但在RAC下会强制使用NOLOGGING + LOCAL分配,导致新数据全堆在当前节点的默认临时段,反而制造新的热点。
- 批量导入时,显式指定分区:用
INSERT INTO t PARTITION (p202401) SELECT ...,让数据落点可控 - 禁用
APPEND不是万能解法——它会让事务变长、undo压力大,需权衡吞吐与一致性要求 - 如果必须用
APPEND,提前在每个节点上运行ALTER TABLE ... ALLOCATE EXTENT,预分配空间,减少运行时争用
真正难的不是语法或参数,是把“数据怎么来”“谁会查”“查多久”“在哪查”这四件事,在建表前就串起来想清楚。漏掉任意一环,后期调优都是补丁叠补丁。










