MySQL高级函数之：`UUID_SHORT()`：其在生成短`UUID`中的应用与性能。

admin
Mon, 01 Sep 2025 09:35:21 +0000
Mysql, mysql, short, uuid

好的，下面开始我们的MySQL高级函数讲座，今天的主题是UUID_SHORT()函数，以及它在生成短UUID中的应用与性能考量。 UUID与UUID_SHORT()：背景知识 UUID（Universally Unique Identifier），通用唯一识别码，是一种标准化的128位格式的字符串，旨在保证在时间和空间上的唯一性。常见的UUID格式是标准的36字符长的字符串，例如：550e8400-e29b-41d4-a716-446655440000。这种格式虽然保证了唯一性，但其存储空间较大，索引效率相对较低，对于某些对存储空间和性能要求较高的场景并不适用。 UUID_SHORT()函数是MySQL提供的一种生成“短UUID”的函数。它返回一个64位的无符号整数，相比标准的128位UUID，大大缩短了长度，从而节省了存储空间，并在一定程度上提升了索引效率。 UUID_SHORT() 的工作原理 UUID_SHORT()函数的实现原理依赖于MySQL服务器的server_id。 该函数基于服务器启动时间和服务器ID来生成唯一值，因此在单台服务器上可以保证唯一性。 但是，在多服务器环境 …

继续阅读“MySQL高级函数之：`UUID_SHORT()`：其在生成短`UUID`中的应用与性能。”

The post MySQL高级函数之：`UUID_SHORT()`：其在生成短`UUID`中的应用与性能。 first appeared on 智猿学院-前后端，数据库，人工智能，云计算等领域前沿技术讲座.

好的，下面开始我们的MySQL高级函数讲座，今天的主题是UUID_SHORT()函数，以及它在生成短UUID中的应用与性能考量。

UUID与UUID_SHORT()：背景知识

UUID（Universally Unique Identifier），通用唯一识别码，是一种标准化的128位格式的字符串，旨在保证在时间和空间上的唯一性。常见的UUID格式是标准的36字符长的字符串，例如：550e8400-e29b-41d4-a716-446655440000。这种格式虽然保证了唯一性，但其存储空间较大，索引效率相对较低，对于某些对存储空间和性能要求较高的场景并不适用。

UUID_SHORT()函数是MySQL提供的一种生成“短UUID”的函数。它返回一个64位的无符号整数，相比标准的128位UUID，大大缩短了长度，从而节省了存储空间，并在一定程度上提升了索引效率。

UUID_SHORT() 的工作原理

UUID_SHORT()函数的实现原理依赖于MySQL服务器的server_id。 该函数基于服务器启动时间和服务器ID来生成唯一值，因此在单台服务器上可以保证唯一性。 但是，在多服务器环境中，如果服务器ID相同，则可能存在冲突的风险。

UUID_SHORT() 的语法

UUID_SHORT()函数没有参数，直接调用即可：

SELECT UUID_SHORT();

UUID_SHORT() 的返回值

UUID_SHORT()函数返回一个64位的无符号整数，例如：18446744073709551615。

UUID_SHORT() 的应用场景

UUID_SHORT()函数主要应用于以下场景：

主键生成： 在对存储空间要求较高的表中，可以使用UUID_SHORT()生成主键，替代传统的自增ID或标准UUID。

唯一标识符： 在某些需要唯一标识符的场景中，可以使用UUID_SHORT()生成唯一标识，例如订单号、产品ID等。

缓存键： 可以使用UUID_SHORT()生成缓存键，避免缓存键冲突。

UUID_SHORT() 的代码示例

1. 创建表并使用UUID_SHORT()作为主键

CREATE TABLE short_uuid_table (
    id BIGINT UNSIGNED PRIMARY KEY,
    name VARCHAR(255)
);

INSERT INTO short_uuid_table (id, name) VALUES (UUID_SHORT(), 'Record 1');
INSERT INTO short_uuid_table (id, name) VALUES (UUID_SHORT(), 'Record 2');

SELECT * FROM short_uuid_table;

2. 使用UUID_SHORT()生成唯一标识符

SELECT UUID_SHORT() AS order_id;

3. 在存储过程中使用UUID_SHORT()

DELIMITER //
CREATE PROCEDURE generate_short_uuid()
BEGIN
    INSERT INTO short_uuid_table (id, name) VALUES (UUID_SHORT(), 'Record from procedure');
END //
DELIMITER ;

CALL generate_short_uuid();

SELECT * FROM short_uuid_table;

UUID_SHORT() 的性能考量

虽然UUID_SHORT()相比标准的UUID缩短了长度，提升了索引效率，但仍然需要考虑其性能影响。

1. 唯一性冲突风险： UUID_SHORT()的唯一性依赖于服务器ID和启动时间。在多服务器环境中，如果服务器ID相同，则可能存在冲突的风险。因此，在使用UUID_SHORT()时，必须确保服务器ID的唯一性。可以使用如下方法在MySQL配置文件中设置server-id:

[mysqld]
server-id=1234

并在每台服务器上设置不同的server-id。

如果需要更高的唯一性保证，可以使用更复杂的UUID生成算法，例如基于时间戳、MAC地址和随机数的算法。

2. 索引效率： UUID_SHORT()虽然比标准UUID短，但仍然是随机生成的，因此在插入数据时可能会导致页分裂，影响索引效率。

为了缓解这个问题，可以考虑以下方法：

使用顺序UUID： 顺序UUID是指UUID的值随着时间递增，这样可以减少页分裂。但MySQL本身并不直接支持顺序UUID的生成，需要通过自定义函数或外部工具生成。

预分配ID： 在插入数据前，先预分配一批ID，然后按照顺序插入数据，这样可以减少页分裂。

3. 数据类型选择： UUID_SHORT()返回的是64位的无符号整数，因此在定义表结构时，必须选择BIGINT UNSIGNED类型。如果选择其他类型，可能会导致数据溢出或精度损失。

4. 并发性能： 在高并发场景下，UUID_SHORT()可能会成为性能瓶颈。因为UUID_SHORT()的生成需要访问服务器的全局状态，可能会导致锁竞争。

为了缓解这个问题，可以考虑以下方法：

批量生成UUID： 在插入数据前，先批量生成一批UUID，然后分发给不同的线程使用，这样可以减少锁竞争。

使用本地缓存： 在每个线程中维护一个本地缓存，存储已经生成的UUID，这样可以避免频繁访问全局状态。

UUID_SHORT() 的替代方案

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

自增ID： 自增ID是最常用的主键生成方式，简单易用，性能高。但自增ID不具备全局唯一性，不适合分布式环境。

雪花算法（Snowflake）： 雪花算法是一种分布式ID生成算法，可以保证全局唯一性和递增性。雪花算法需要依赖于时间戳和机器ID，因此需要配置正确的时钟和机器ID。

ULID（Universally Unique Lexicographically Sortable Identifier）： ULID 是一种旨在替代 UUID 的 ID 标准。 它具有 128 位的兼容 UUID 的唯一性，并且按词法可排序！ULID 由两部分组成：一个 48 位的 Unix 纪元时间戳（以毫秒为单位）和一个 80 位的随机数。

自定义UUID生成算法： 可以根据实际需求，自定义UUID生成算法，例如基于时间戳、MAC地址和随机数的算法。

UUID_SHORT()与其他UUID生成方法的比较

特性 | UUID_SHORT() | 标准 UUID (UUID()) | 自增ID | 雪花算法 | ULID
长度 | 64位整数 | 128位字符串 | 整数 | 64位整数 | 128位字符
唯一性 | 单机相对唯一 | 全局唯一 | 单表唯一 | 全局唯一 | 全局唯一
全局唯一性 | 低 | 高 | 低 | 高 | 高
递增性 | 无 | 无 | 有 | 近似递增 | 近似递增
存储空间 | 小 | 大 | 小 | 小 | 大
索引效率 | 中 | 低 | 高 | 中 | 中
实现复杂度 | 简单 | 简单 | 简单 | 复杂 | 中等
分布式支持 | 差 | 好 | 差 | 好 | 好
是否依赖外部服务 | 否 | 否 | 否 | 是 | 否

最佳实践

1. 确保服务器ID唯一： 在使用UUID_SHORT()时，必须确保服务器ID的唯一性。

2. 考虑唯一性冲突风险： 在多服务器环境中，需要考虑唯一性冲突的风险，并采取相应的措施。

3. 选择合适的数据类型： UUID_SHORT()返回的是64位的无符号整数，因此在定义表结构时，必须选择BIGINT UNSIGNED类型。

4. 关注索引效率： UUID_SHORT()是随机生成的，因此在插入数据时可能会导致页分裂，影响索引效率。可以考虑使用顺序UUID或预分配ID来缓解这个问题。

5. 评估并发性能： 在高并发场景下，UUID_SHORT()可能会成为性能瓶颈。可以考虑批量生成UUID或使用本地缓存来缓解这个问题。

6. 根据实际需求选择合适的UUID生成方案： UUID_SHORT()只是一种UUID生成方案，需要根据实际需求选择合适的方案。

代码示例： 使用UUID_SHORT并解决潜在冲突 (单机多实例)

假设你在同一台机器上运行了多个MySQL实例，为了避免UUID_SHORT冲突，你需要确保每个实例的server_id是唯一的。

-- 实例1: server_id = 1
-- 在 my.cnf 或 my.ini 中设置 server-id=1

-- 实例2: server_id = 2
-- 在 my.cnf 或 my.ini 中设置 server-id=2

-- 每个实例分别执行以下代码创建表和插入数据
CREATE TABLE unique_ids (
    id BIGINT UNSIGNED PRIMARY KEY,
    instance_name VARCHAR(255)
);

INSERT INTO unique_ids (id, instance_name) VALUES (UUID_SHORT(), 'instance_1'); -- 在实例1上执行
INSERT INTO unique_ids (id, instance_name) VALUES (UUID_SHORT(), 'instance_2'); -- 在实例2上执行

-- 为了验证唯一性，你可以将两个实例的数据合并到一个表中进行比较（仅用于验证，生产环境避免跨实例直接操作数据）
CREATE TABLE combined_ids AS
SELECT id, instance_name FROM instance_1.unique_ids
UNION ALL
SELECT id, instance_name FROM instance_2.unique_ids;

SELECT id, COUNT(*) FROM combined_ids GROUP BY id HAVING COUNT(*) > 1; -- 如果结果为空，说明没有冲突

这段代码演示了如何在单机多实例的情况下，通过配置不同的server_id来避免UUID_SHORT的冲突。 注意，生产环境中不建议直接跨实例操作数据，这里只是为了方便验证。

代码示例： 使用预分配ID来提升插入性能

为了减少由于随机UUID_SHORT导致的页分裂，可以预先生成一批ID，然后按顺序插入数据。

-- 1. 创建存储预分配ID的临时表
CREATE TEMPORARY TABLE pre_allocated_ids (
    id BIGINT UNSIGNED PRIMARY KEY
);

-- 2. 预先生成一批UUID_SHORT
DELIMITER //
CREATE PROCEDURE generate_ids(IN num_ids INT)
BEGIN
    DECLARE i INT DEFAULT 0;
    WHILE i < num_ids DO
        INSERT INTO pre_allocated_ids (id) VALUES (UUID_SHORT());
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

CALL generate_ids(1000); -- 预生成1000个ID

-- 3. 创建实际使用的表
CREATE TABLE data_table (
    id BIGINT UNSIGNED PRIMARY KEY,
    data VARCHAR(255)
);

-- 4. 从预分配表中按顺序取出ID并插入数据
INSERT INTO data_table (id, data)
SELECT id, 'some data' FROM pre_allocated_ids ORDER BY id;

-- 5. 清理临时表
DROP TEMPORARY TABLE pre_allocated_ids;

这段代码演示了如何通过预分配ID来提升插入性能。预分配ID可以保证ID的顺序性，从而减少页分裂。 注意，预分配的ID数量需要根据实际需求进行调整。

总结：UUID_SHORT() 的选择与权衡

UUID_SHORT()函数在MySQL中提供了一种生成短UUID的便捷方式，适用于对存储空间和性能有一定要求的场景。然而，它也存在唯一性冲突的风险和索引效率问题。在使用UUID_SHORT()时，需要充分考虑其优缺点，并根据实际需求选择合适的UUID生成方案。 在多服务器环境中，务必确保服务器ID的唯一性，并考虑使用顺序UUID或预分配ID等方法来提升性能。

未来展望：更高效的短UUID方案

未来，MySQL可能会引入更高效的短UUID生成方案，例如基于硬件加速的UUID生成算法，或者支持顺序UUID的生成。这些方案将进一步提升UUID的性能和可靠性，使其在更多场景中得到应用。