oracle主键使用uuid
一、Oracle B 树索引的插入逻辑
Oracle 主键索引(B 树结构)的叶子节点是按主键值有序排列的双向链表,插入数据时的逻辑:
- 找到主键值对应的叶子节点位置;
- 若节点有空闲空间,直接插入;
- 若节点已满(默认页填充率
PCTFREE=10,即 90% 满),触发页分裂:将原节点拆分为两个节点,重新分配数据,保持 B 树平衡。
二、UUID 作为主键的性能问题根源
UUID 是 32 位的随机十六进制字符串(如 8f9e7d6b-5c4a-3b2a-1d0e-9f8e7d6c5b4a),其核心问题是值的随机性,与自增主键(如序列生成的数字)形成鲜明对比:
| 维度 | 自增主键(序列) | UUID 主键 |
|---|---|---|
| 插入位置 | 叶子节点末尾(顺序插入) | 叶子节点随机位置 |
| 页分裂频率 | 极低(仅当末尾节点满时分裂) | 极高(每次插入大概率碰满节点) |
| 索引页填充率 | 高(约 85-90%) | 低(常降至 50% 以下) |
| 索引碎片化程度 | 几乎无 | 严重 |
具体性能问题表现
-
插入性能大幅下降
- 频繁页分裂:每次分裂需要读写磁盘(拆节点、更新指针),是高开销操作;
- 空间浪费:索引页填充率低,同样数据量下,UUID 主键索引的磁盘占用是自增主键的 2 倍以上;
- 锁竞争:随机插入可能导致多个会话竞争同一索引页的锁,加剧插入延迟。
-
查询性能下降
- 碎片化导致索引页数量激增,查询时需要加载更多页(IO 次数增加);
- B 树高度升高:自增主键的 B 树高度通常为 2(千万级数据),UUID 主键可能升至 3,查询时多一次磁盘 IO;
- 范围查询低效:UUID 无业务顺序,
BETWEEN/ORDER BY等范围查询无法利用 B 树的有序性优势。
-
维护成本高 为了缓解碎片化,你需要定期手动重建/重组索引(如
ALTER INDEX idx_pk_uuid REBUILD ONLINE),但:- 离线重建会锁表,影响业务;
- 在线重建(ONLINE)虽不锁表,但会产生大量 redo/undo 日志,占用数据库资源。