MySQL函数：`UUID_SHORT()`生成更短的唯一标识符，适用于需要紧凑存储的场景。

admin
Sun, 14 Sep 2025 07:47:34 +0000
Mysql, mysql, short, uuid

MySQL 函数 UUID_SHORT()：短小精悍的唯一标识符 大家好，今天我们来深入探讨 MySQL 中的 UUID_SHORT() 函数。在很多应用场景中，我们需要生成唯一的标识符来区分不同的记录。UUID（Universally Unique Identifier）是一种常见的选择，但标准的 UUID 长度为 36 个字符（包含连字符），存储和索引效率相对较低。UUID_SHORT() 函数应运而生，它生成一个更短的唯一标识符，在保证一定程度唯一性的前提下，优化了存储空间和查询性能。 1. UUID 和 UUID_SHORT() 的对比 首先，我们简单回顾一下 UUID 的特性。标准的 UUID 是一个 128 位的数字，通常以 8-4-4-4-12 的十六进制格式表示。例如：550e8400-e29b-41d4-a716-446655440000。 UUID 的优点在于其全局唯一性，即使在不同的系统和数据库中生成，冲突的概率也非常低。但是，由于其长度较长，在数据库中作为主键或索引时，会占用较多的存储空间，并且可能降低查询效率。 UUID_SHORT() 函数则提供了一种折衷方 …

继续阅读“MySQL函数：`UUID_SHORT()`生成更短的唯一标识符，适用于需要紧凑存储的场景。”

The post MySQL函数：`UUID_SHORT()`生成更短的唯一标识符，适用于需要紧凑存储的场景。 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

MySQL 函数 UUID_SHORT()：短小精悍的唯一标识符

大家好，今天我们来深入探讨 MySQL 中的 UUID_SHORT() 函数。在很多应用场景中，我们需要生成唯一的标识符来区分不同的记录。UUID（Universally Unique Identifier）是一种常见的选择，但标准的 UUID 长度为 36 个字符（包含连字符），存储和索引效率相对较低。UUID_SHORT() 函数应运而生，它生成一个更短的唯一标识符，在保证一定程度唯一性的前提下，优化了存储空间和查询性能。

1. UUID 和 UUID_SHORT() 的对比

首先，我们简单回顾一下 UUID 的特性。标准的 UUID 是一个 128 位的数字，通常以 8-4-4-4-12 的十六进制格式表示。例如：550e8400-e29b-41d4-a716-446655440000。

UUID 的优点在于其全局唯一性，即使在不同的系统和数据库中生成，冲突的概率也非常低。但是，由于其长度较长，在数据库中作为主键或索引时，会占用较多的存储空间，并且可能降低查询效率。

UUID_SHORT() 函数则提供了一种折衷方案。它生成的标识符长度更短，通常为 64 位整数，这意味着它占用的存储空间更少，索引效率更高。然而，与 UUID 相比，UUID_SHORT() 的唯一性有所降低，在特定的应用场景下可能需要额外考虑冲突问题。

特性 | UUID | UUID_SHORT()
长度 | 36 字符 (包含连字符) | 64 位整数 (通常显示为无符号 BIGINT)
唯一性 | 全局唯一 | 相对唯一 (依赖于服务器 ID 和时间戳)
存储空间 | 较大 | 较小
索引效率 | 较低 | 较高
适用场景 | 绝对唯一性要求，分布式系统，数据同步等 | 内部系统，数据量大，对性能要求高的场景等

2. UUID_SHORT() 的工作原理

UUID_SHORT() 函数的实现依赖于 MySQL 服务器的 server_id 和当前的时间戳。其基本原理是将 server_id 和时间戳组合起来，生成一个唯一的 64 位整数。

具体来说，UUID_SHORT() 的生成过程大致如下：

1. 获取 server_id: server_id 是 MySQL 服务器的唯一标识符，可以在 my.cnf 配置文件中设置。如果没有设置，MySQL 会自动生成一个。

2. 获取当前时间戳: UUID_SHORT() 获取当前的时间戳，通常是自 Unix 纪元 (1970-01-01 00:00:00 UTC) 以来的秒数或毫秒数。

3. 组合 server_id 和时间戳: UUID_SHORT() 将 server_id 和时间戳进行组合，通常采用位运算的方式，例如将 server_id 左移若干位，然后与时间戳进行或运算。

4. 返回 64 位整数: UUID_SHORT() 返回一个 64 位的无符号整数，作为唯一的标识符。

需要注意的是，UUID_SHORT() 的唯一性依赖于 server_id 的唯一性。如果多台 MySQL 服务器使用相同的 server_id，则生成的标识符可能会冲突。因此，在部署 MySQL 集群时，务必确保每个服务器的 server_id 都是唯一的。

3. UUID_SHORT() 的语法和用法

UUID_SHORT() 函数的语法非常简单：

UUID_SHORT()

它不接受任何参数，直接调用即可生成一个唯一的标识符。

下面是一些 UUID_SHORT() 的用法示例：

3.1 生成 UUID_SHORT 值

SELECT UUID_SHORT();

执行结果类似于：

18446744073709551615

3.2 将 UUID_SHORT 作为主键

CREATE TABLE users (
    id BIGINT UNSIGNED PRIMARY KEY,
    username VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL
);

INSERT INTO users (id, username, email) VALUES (UUID_SHORT(), 'john_doe', 'john.doe@example.com');
INSERT INTO users (id, username, email) VALUES (UUID_SHORT(), 'jane_doe', 'jane.doe@example.com');

SELECT * FROM users;

3.3 在触发器中使用 UUID_SHORT

CREATE TABLE orders (
    id BIGINT UNSIGNED PRIMARY KEY,
    user_id BIGINT UNSIGNED NOT NULL,
    order_date DATETIME NOT NULL
);

DELIMITER //
CREATE TRIGGER before_insert_orders
BEFORE INSERT ON orders
FOR EACH ROW
BEGIN
    SET NEW.id = UUID_SHORT();
END;//
DELIMITER ;

INSERT INTO orders (user_id, order_date) VALUES (123, NOW());

SELECT * FROM orders;

3.4 server_id 配置

在 my.cnf 配置文件中设置 server_id：

[mysqld]
server-id=1

重启 MySQL 服务器后，UUID_SHORT() 生成的标识符将包含该 server_id。

4. UUID_SHORT() 的局限性和注意事项

虽然 UUID_SHORT() 在存储空间和索引效率方面具有优势，但也存在一些局限性，需要在使用时注意：

4.1 唯一性问题

UUID_SHORT() 的唯一性不如标准的 UUID。如果多台服务器使用相同的 server_id，或者在短时间内生成大量的标识符，可能会发生冲突。因此，在对唯一性要求非常高的场景下，不建议使用 UUID_SHORT()。

4.2 server_id 配置的重要性

server_id 是 UUID_SHORT() 唯一性的关键。务必确保每个 MySQL 服务器的 server_id 都是唯一的。如果没有配置 server_id，MySQL 会自动生成一个，但这可能会导致在迁移或备份恢复后，server_id 发生变化，从而导致标识符冲突。

4.3 时间戳的精度

UUID_SHORT() 的唯一性还依赖于时间戳的精度。如果时间戳的精度较低（例如秒级），则在短时间内生成大量标识符时，可能会发生冲突。

4.4 并发环境下的冲突

在高并发环境下，即使 server_id 和时间戳都不同，UUID_SHORT() 仍然存在一定的冲突概率。为了降低冲突概率，可以考虑使用更精确的时间戳，或者结合其他因素来生成标识符。

4.5 排序问题

UUID_SHORT() 生成的标识符是基于时间戳的，因此在一定程度上是递增的。但是，由于 server_id 的影响，以及时间戳的精度问题，UUID_SHORT() 生成的标识符并不总是严格递增的。如果需要严格递增的标识符，可以考虑使用自增主键或其他方式。

5. 替代方案

如果 UUID_SHORT() 无法满足你的需求，可以考虑以下替代方案：

自增主键: 自增主键是一种简单有效的唯一标识符生成方式。它可以保证唯一性和递增性，但缺点是无法跨数据库或系统使用。

ULID (Universally Unique Lexicographically Sortable Identifier): ULID 是一种长度为 26 个字符的唯一标识符，它结合了时间戳和随机数，具有可排序的特性，并且冲突概率较低。

雪花算法 (Snowflake): 雪花算法是一种分布式 ID 生成算法，它可以生成 64 位的唯一标识符，并且可以保证全局唯一性和递增性。雪花算法需要在应用程序中实现，而不是直接使用数据库函数。

方案 | 优点 | 缺点 | 适用场景
自增主键 | 简单易用，唯一性和递增性保证 | 无法跨数据库或系统使用 | 单个数据库，不需要全局唯一性
UUID_SHORT() | 占用空间小，索引效率高 | 唯一性不如 UUID，需要注意 server_id 配置和冲突问题 | 内部系统，数据量大，对性能要求高的场景
ULID | 长度适中，可排序，冲突概率较低 | 需要额外的库或函数支持 | 需要可排序的唯一标识符，对唯一性要求较高的场景
雪花算法 | 全局唯一，递增性保证，可扩展性强 | 需要在应用程序中实现，配置相对复杂 | 分布式系统，需要全局唯一性和递增性的场景

6. 代码示例：结合 UUID_SHORT() 和 MD5 生成唯一标识符

为了进一步降低 UUID_SHORT() 的冲突概率，我们可以将其与其他哈希函数结合使用，例如 MD5。

CREATE FUNCTION generate_unique_id()
RETURNS VARCHAR(32)
DETERMINISTIC
BEGIN
    DECLARE short_uuid BIGINT UNSIGNED;
    DECLARE md5_hash VARCHAR(32);

    SET short_uuid = UUID_SHORT();
    SET md5_hash = MD5(CAST(short_uuid AS CHAR));

    RETURN md5_hash;
END;

SELECT generate_unique_id();

这个函数首先生成一个 UUID_SHORT() 值，然后将其转换为字符串，并使用 MD5 函数计算其哈希值。这样生成的标识符长度为 32 个字符，并且冲突概率更低。

7. 代码示例：使用 UUID_SHORT() 优化查询性能

假设我们有一个 products 表，其中包含大量的商品信息。为了提高查询性能，我们可以使用 UUID_SHORT() 作为主键，并创建一个索引。

CREATE TABLE products (
    id BIGINT UNSIGNED PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    price DECIMAL(10, 2) NOT NULL
);

ALTER TABLE products ADD INDEX idx_name (name);

-- 插入大量数据
INSERT INTO products (id, name, price) VALUES (UUID_SHORT(), 'Product A', 10.00);
INSERT INTO products (id, name, price) VALUES (UUID_SHORT(), 'Product B', 20.00);
-- ... 插入更多数据 ...

-- 查询商品名称为 'Product A' 的商品
SELECT * FROM products WHERE name = 'Product A';

由于 UUID_SHORT() 占用的存储空间较小，索引效率较高，因此可以显著提高查询性能。

8. 代码示例：使用 UUID_SHORT() 进行数据分片

在某些场景下，我们需要将数据分散到多个数据库或表中，以提高系统的可扩展性和性能。UUID_SHORT() 可以用于数据分片。

-- 创建多个分片表
CREATE TABLE products_0 (
    id BIGINT UNSIGNED PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    price DECIMAL(10, 2) NOT NULL
);

CREATE TABLE products_1 (
    id BIGINT UNSIGNED PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    price DECIMAL(10, 2) NOT NULL
);

-- ... 创建更多分片表 ...

-- 插入数据时，根据 UUID_SHORT() 的值选择分片表
DELIMITER //
CREATE PROCEDURE insert_product(IN product_name VARCHAR(255), IN product_price DECIMAL(10, 2))
BEGIN
    DECLARE short_uuid BIGINT UNSIGNED;
    DECLARE shard_id INT;

    SET short_uuid = UUID_SHORT();
    SET shard_id = short_uuid % 2; -- 假设有两个分片表

    IF shard_id = 0 THEN
        INSERT INTO products_0 (id, name, price) VALUES (short_uuid, product_name, product_price);
    ELSE
        INSERT INTO products_1 (id, name, price) VALUES (short_uuid, product_name, product_price);
    END IF;
END;//
DELIMITER ;

CALL insert_product('Product C', 30.00);

这个示例根据 UUID_SHORT() 的值选择不同的分片表，从而将数据分散到多个表中。

9. 实际应用场景分析

内部系统: 在不需要全局唯一性的内部管理系统或日志系统中，UUID_SHORT() 可以作为主键，节省存储空间并提高查询速度。例如，一个内部的工单系统，工单ID可以使用UUID_SHORT()，减轻数据库压力。

高并发场景: 在需要快速生成大量唯一标识符的高并发场景下，UUID_SHORT() 可以作为一种选择，但需要注意冲突问题，并采取相应的措施（例如结合 MD5）。

数据分片: UUID_SHORT() 可以用于数据分片，将数据分散到多个数据库或表中，提高系统的可扩展性和性能。

临时表: 在创建临时表时，使用 UUID_SHORT() 可以避免主键冲突，并提高创建速度。

UUID_SHORT() 的优势和不足

UUID_SHORT() 函数在MySQL中提供了一种生成较短唯一标识符的方案，适用于对存储空间和性能有较高要求的场景。理解其工作原理、局限性和替代方案，可以帮助我们更好地选择合适的标识符生成方式，并优化数据库性能。务必仔细评估其唯一性是否满足应用需求，并正确配置 server_id，以避免潜在的冲突问题。