oracle主键使用uuid

一、Oracle B 树索引的插入逻辑

Oracle 主键索引(B 树结构)的叶子节点是按主键值有序排列的双向链表,插入数据时的逻辑:

  1. 找到主键值对应的叶子节点位置;
  2. 若节点有空闲空间,直接插入;
  3. 若节点已满(默认页填充率 PCTFREE=10,即 90% 满),触发页分裂:将原节点拆分为两个节点,重新分配数据,保持 B 树平衡。

二、UUID 作为主键的性能问题根源

UUID 是 32 位的随机十六进制字符串(如 8f9e7d6b-5c4a-3b2a-1d0e-9f8e7d6c5b4a),其核心问题是值的随机性,与自增主键(如序列生成的数字)形成鲜明对比:

维度 自增主键(序列) UUID 主键
插入位置 叶子节点末尾(顺序插入) 叶子节点随机位置
页分裂频率 极低(仅当末尾节点满时分裂) 极高(每次插入大概率碰满节点)
索引页填充率 高(约 85-90%) 低(常降至 50% 以下)
索引碎片化程度 几乎无 严重

具体性能问题表现

  1. 插入性能大幅下降

    • 频繁页分裂:每次分裂需要读写磁盘(拆节点、更新指针),是高开销操作;
    • 空间浪费:索引页填充率低,同样数据量下,UUID 主键索引的磁盘占用是自增主键的 2 倍以上;
    • 锁竞争:随机插入可能导致多个会话竞争同一索引页的锁,加剧插入延迟。
  2. 查询性能下降

    • 碎片化导致索引页数量激增,查询时需要加载更多页(IO 次数增加);
    • B 树高度升高:自增主键的 B 树高度通常为 2(千万级数据),UUID 主键可能升至 3,查询时多一次磁盘 IO;
    • 范围查询低效:UUID 无业务顺序,BETWEEN/ORDER BY 等范围查询无法利用 B 树的有序性优势。
  3. 维护成本高 为了缓解碎片化,你需要定期手动重建/重组索引(如 ALTER INDEX idx_pk_uuid REBUILD ONLINE),但:

    • 离线重建会锁表,影响业务;
    • 在线重建(ONLINE)虽不锁表,但会产生大量 redo/undo 日志,占用数据库资源。