使用 MySQL 生成非顺序、仅限整数的 UUID 的最快方法?

Posted

技术标签:

【中文标题】使用 MySQL 生成非顺序、仅限整数的 UUID 的最快方法?【英文标题】:Fastest way to generate a non-sequential, integers-only UUID with MySQL? 【发布时间】:2022-01-22 10:13:42 【问题描述】:

我正在尝试使用 mysql 生成 非顺序仅整数 UUID,并尽可能获得最佳性能。

我知道 MySQL 已经提供了多种方法来生成可靠的 UUID:

UUID v4:非常独特,但 slow 并存储为 UUID 类型 UUID v1:类似,但可以是连续的,稍微提高索引性能 UUID_SHORT(): 最佳性能,更短,存储在 64 位 BIG INT 上,但连续

但是,这些解决方案都没有提供非顺序(它将公开显示,我不希望用户能够跟踪增长/增量)仅整数 UUID (用于性能)。

使用 RAND() 是不可能的,因为冲突太高,即使对于

除了将 UUID_V1 转换为十进制之外,还有什么聪明的解决方案吗?

【问题讨论】:

RAND() 不是碰撞安全的。 我认为他的意思是有可能随机生成 2 个相同 id 的机会,尽管机会很小。如果一切都失败了,您可以生成一个普通的 GUID,删除 - 字符,然后使用 CONV 将其从基数 16 转换为基数 10。这将为您提供 20 位数字。 @Simulant 即使 uuid 也不能保证避免碰撞。这是可以接受的,因为碰撞的可能性是如此之小,以至于人们认为它“永远不会”发生。 @Bruno 为 1M 记录使用 2^32 个 uuid,您保证会发生冲突。在大约 70K 行中,有 50% 的变化是两个将具有相同的 uuid。请参阅Birthday problem 了解为什么会这样。至少需要 64 位的 uuid,128 位会更好。 您是否想要nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnn 形式的字符串,其中n 是数字(不是字母十六进制字符)?还是nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn 好吗? 【参考方案1】:

您的问题首先是数学问题,然后是编程问题。

我会考虑简单的:M = (M + N) % (2^32) 来获得 M 的“下一个”值。

其中 N 是一个大的正奇整数。

M 是要使用的“下一个”数字。 (它可以用你喜欢的任何东西初始化)。

它将生成 2^32 个不同的数字,然后重复。

2^32 可以是 2 的任意幂。实际上,关键是 2^32 和 N 没有任何共同因子(1 除外)。

小心%;您使用的语言可能使用 32 位有符号数字。或者可能是 64 位的。在当今的大多数语言中,2^16 都可以使用。但它会将您限制为 65536 个值。

% 2^P 也可以使用位掩码来完成。

Rand() 仅在 2^30 个值后重复,但 RAND() * 99999 可能在前 99999 次迭代中有一些重复。有些随机数生成器持续时间更长。

1M 值大约是 20 位。所以 2^20 有效。或使用& 0xFFFFF 屏蔽。

如果您还转换为十六进制,则所有代码都可以是 5 个字符。 TO_BASE64() 会将其压缩为 4 个字符。

【讨论】:

以上是关于使用 MySQL 生成非顺序、仅限整数的 UUID 的最快方法?的主要内容,如果未能解决你的问题,请参考以下文章

如何选择主键uuid

生成随机 UUID 非阻塞

Rails + UUID 生成的模式假定 UUID 是整数而不是字符串

nodejs中生成uuid

MySQL uuid()函数生成的UUID的长度问题

插入php后获取生成的uuid