UUID vs 自增 ID:数据库主键选择指南

全面对比 UUID 和自增 ID 作为数据库主键的优缺点,帮助你做出正确的技术选型。

UUID 专题 2026-06-02 8 分钟

UUID vs 自增 ID:数据库主键选择指南

选择数据库主键是数据库设计的核心决策。本文对比 UUID 和自增 ID 的优缺点。

对比总览

特性 自增 ID UUID
唯一性 单库唯一 全局唯一
有序性 ✅ 有序 ❌ 无序(V4)
存储大小 4-8 字节 16 字节
可预测性 可预测 不可预测
分布式支持 ❌ 需要协调 ✅ 无需协调
安全性 低(可遍历) 高(不可遍历)
性能

自增 ID

优势

  1. 性能好:B+ 树插入有序,页分裂少
  2. 存储小:4 字节(INT)或 8 字节(BIGINT)
  3. 可读性好:1, 2, 3 简单直观
  4. 调试方便:容易追踪数据

劣势

  1. 分布式困难:多库需要协调,避免 ID 冲突
  2. 安全性低:可遍历,容易被猜测
  3. 数据迁移麻烦:不同库的 ID 可能冲突
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100)
);

UUID

优势

  1. 全局唯一:无需协调,各节点独立生成
  2. 安全性高:不可遍历,难以猜测
  3. 数据迁移方便:不同库的数据可以合并
  4. 离线生成:不依赖数据库

劣势

  1. 性能差:无序插入导致页分裂
  2. 存储大:16 字节,比 BIGINT 大一倍
  3. 可读性差:难以记忆和调试
  4. 索引碎片化:随机插入导致索引碎片
CREATE TABLE users (
    id CHAR(36) PRIMARY KEY,
    name VARCHAR(100)
);

性能测试

插入性能(100 万条数据)

方案 耗时 索引大小
自增 ID 12s 30MB
UUID V4 25s 65MB
有序 UUID 14s 35MB

查询性能(按 ID 查询)

方案 平均耗时
自增 ID 0.1ms
UUID V4 0.3ms
有序 UUID 0.15ms

选型建议

选择自增 ID 的场景

  • 单库单表
  • 内部系统(不需要隐藏 ID)
  • 性能要求极高
  • 数据量不大(< 1 亿)

选择 UUID 的场景

  • 分布式系统
  • 需要数据合并
  • 安全性要求高(不暴露 ID)
  • 需要离线生成 ID

混合方案

-- 内部使用自增 ID,外部暴露 UUID
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    uuid CHAR(36) UNIQUE NOT NULL,
    name VARCHAR(100)
);

-- 查询时使用 UUID
SELECT * FROM users WHERE uuid = 'xxx';

-- 内部关联使用自增 ID
SELECT * FROM orders WHERE user_id = 123;

优化方案

1. 有序 UUID

// 使用时间戳前缀
public static UUID orderedUUID() {
    long time = System.currentTimeMillis();
    UUID uuid = UUID.randomUUID();
    return new UUID(
        (time << 22) | (uuid.getMostSignificantBits() & 0x3FFFFF),
        uuid.getLeastSignificantBits()
    );
}

2. Snowflake 算法

// 64 位有序 ID
long id = snowflake.nextId();
// 1635123456789012345

3. ULID

01ARZ3NDEKTSV4RRFFQ69G5FAV

总结

没有绝对的好坏,关键是根据场景选择:

  • 单库、性能优先 → 自增 ID
  • 分布式、安全优先 → UUID
  • 需要有序 + 分布式 → Snowflake 或有序 UUID

📚 相关文章