【问题标题】:Why so many collisions with the MariaDB 10.2 RAND() function?为什么与 MariaDB 10.2 RAND() 函数发生如此多的冲突?
【发布时间】:2020-02-13 16:03:50
【问题描述】:

注意:在 Windows Server 2012 R2 Standard 上运行 MariaDB 10.2.27。

我想生成用于 MariaDB 的随机整数,所以我一直在尝试 MariaDB RAND() 函数。要么我的期望和理解偏离了基础(绝对有可能!),要么 MariaDB RAND() 函数不是很随机。

使用 BIGINT(20) 列我想生成长度不超过 16 位的随机整数,所以我使用了这个 SQL:FLOOR(RAND()*9999999999999999)+1)。我在循环中使用的确切 SQL 是:

INSERT INTO rnd_test VALUES (FLOOR(RAND()*9999999999999999)+1);

表 rnd_test 有一列是 BIGINT(20) 并且是主 ID。

使用 10^16 个数字池并考虑生日悖论,我预计在生成 10^8 个数字后发生碰撞的可能性约为 50%。显然这有一些差异,但每次我运行插入循环时,我几乎立即开始看到冲突,然后每隔 2000 或 3000 个生成的数字重复一次,有时更频繁。在生成了大约 50,000 个随机数后,我每隔几百个数字就会看到一次冲突。

认为我的理解可能非常不正确,我调整了循环的 vb.net 代码以在本地生成随机数,然后将其插入到 MariaDB 表中。我在例程顶部定义了一个新的 System.Random,然后使用它来生成随机数:

Dim r As Long = CLng(Math.Floor(rNum.NextDouble() * 9999999999999999)) + 1

通常这会更好,但仍然不如我预期的那么好。它通常会在碰撞发生之前运行大约 100,000 次迭代,然后每生成 10,000 个随机数似乎就有一到两次碰撞。有时一批 10,000 会完全没有任何碰撞。

那么,与 vb.net 函数相比,为什么 MariaDB RAND() 函数的性能如此差?

【问题讨论】:

  • 我建议改用 uuid
  • 同意,这就是我到现在为止需要随机 ID 时所做的事情。不幸的是,在这种情况下,我没有那个选项。我特别需要随机整数。
  • rand() 产生一个只有 16 位精度的双精度数。那肯定会影响碰撞率。您应该能够通过两次调用 rand() 来做您想做的事情。
  • @Ian 您可以将 uuid 转换为(大)整数。
  • 另一种选择:获取 uuid,然后是 uuid 的 sha1 或 md5,将其切割为 64 位(前 16 个字符),转换为 64 位整数。应该是优秀的品质。

标签: mysql sql random mariadb


【解决方案1】:

对 5.6 的 RAND 的进一步实验表明,只有 30 位是好的。也就是说,它只有大约十亿个不同的值。

向 bugs.mysql.com 和/或 MariaDB 提交错误。

30 位对于大多数应用程序来说已经足够了。在那些它不够好的应用中,大多数人不会注意到它的懦弱。

FLOAT 具有 24 位精度; DOUBLE 有 53 个。所以 30 个需要 DOUBLE,但未能填满。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2014-12-16
  • 1970-01-01
  • 1970-01-01
  • 2019-09-20
  • 2013-11-26
  • 2021-08-28
  • 2016-04-07
  • 2015-08-29
相关资源
最近更新 更多