mysql中存放uuid类型问题?

请教大佬,在实际开发实践中,mysql中uuid用什么类型存放比较好?

阅读 1.8k
2 个回答

在 MySQL 中存储 UUID 时,需要注意以下几个关键问题及优化方案:

1. 存储方式选择

方案对比

存储方式长度特点示例值
CHAR(36)36 字节可读性好,但占用空间较大550e8400-e29b-41d4-a716-446655440000
BINARY(16)16 字节存储高效,需转换函数处理0x550E8400E29B41D4A716446655440000

优化建议

MySQL 8.0+ 使用 BINARY(16) + 内置函数:

-- 写入时转换
INSERT INTO table (uuid_col) VALUES (UUID_TO_BIN('550e8400...'));

-- 读取时转换
SELECT BIN_TO_UUID(uuid_col) FROM table;

旧版本 MySQL 可手动移除连字符并存储为 BINARY(16):

-- 应用层处理(如Java)
String uuidStr = uuid.toString().replace("-", "");

2. 主键性能优化

问题

  • 随机性导致性能下降:UUID 的随机性会使 InnoDB 主键索引频繁分裂,影响插入性能。

解决方案

  • 有序 UUID (时间戳前置)
    改造 UUID 结构,使前半部分包含时间信息(如 UUIDv6/v7),提升索引连续性。

    -- 示例:应用层生成有序UUID后存储
    INSERT INTO table (id) VALUES (UUID_TO_BIN(ordered_uuid, true));
  • 组合主键
    使用 AUTO_INCREMENT 列作为主键,额外增加 UUID 列用于业务标识:

    CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    uuid BINARY(16) UNIQUE NOT NULL,
    ...
    );

3. 函数与索引优化

函数处理
利用 UUID_TO_BIN swap_flag 参数优化排序:

-- 第二个参数为 true 时交换时间部分到开头
SELECT BIN_TO_UUID(uuid_col, true) FROM table ORDER BY uuid_col;

前缀索引
CHAR(36) 列使用前缀索引(虽不推荐,但可减少空间):

CREATE INDEX idx_uuid_prefix ON table (uuid_col(8));

4. 应用场景决策

何时使用 UUID

  • ✅ 分布式系统需要全局唯一标识
  • ✅ 需要提前生成 ID(如客户端生成)
  • ✅ 安全要求高,避免 ID 猜测

何时避免 UUID

  • ❌ 单机高并发写入场景(优先考虑 AUTO_INCREMENT
  • ❌ 存储敏感型应用(可用 SMALLER 类型替代)

5. 完整表示例

CREATE TABLE orders (
  id BINARY(16) PRIMARY KEY,
  user_id BINARY(16) NOT NULL,
  amount DECIMAL(10,2)
);

-- 插入数据(有序UUID)
INSERT INTO orders (id, user_id, amount) 
VALUES 
  (UUID_TO_BIN(UUID(), true), 
  (UUID_TO_BIN('123e4567-e89b-12d3-a456-426614174000'), 
  99.95
);

-- 查询时转换回字符串
SELECT 
  BIN_TO_UUID(id, true) AS order_id,
  BIN_TO_UUID(user_id) AS user_id,
  amount 
FROM orders;

总结建议

  1. MySQL 8.0+ 优先使用 BINARY(16) + 内置函数
  2. 高写入场景考虑有序 UUID 或组合主键
  3. 避免在频繁查询的列上使用 CHAR(36)
  4. 索引列尽量使用二进制存储减少空间占用

推荐使用BINARY(16) 来存储UUID。

mysql8.0写法

-- 创建表时使用BINARY(16)存储UUID
CREATE TABLE example_table (
    id BINARY(16) PRIMARY KEY,
    name VARCHAR(255)
);

-- 插入数据时转换UUID
INSERT INTO example_table (id, name) VALUES (UUID_TO_BIN(UUID()), 'example_name');

-- 查询数据时转换回UUID
SELECT BIN_TO_UUID(id) AS id, name FROM example_table;

mysql5.6写法

-- 创建表时使用 BINARY(16) 存储 UUID
CREATE TABLE example_table (
    id BINARY(16) PRIMARY KEY,
    name VARCHAR(255)
);

-- 插入数据时将 UUID 转换为二进制格式
INSERT INTO example_table (id, name)
VALUES (UNHEX(REPLACE(UUID(), '-', '')), 'example_name');

-- 查询数据时将二进制格式的 UUID 转换回可读格式
SELECT HEX(id) AS id, name
FROM example_table;
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题