5

我有一个只有几行的表(前 50 行),我需要从表中获取随机值我可以做到这一点
ORDER BY RAND() LIMIT 1
主要问题是当我在 5 秒内有 6k 次选择时,rand stil 是否“可靠”?兰特是如何计算的,我可以随着时间的推移播种吗?(idk,每 5 秒)。

4

3 回答 3

5

MySQL 伪随机数生成器是完全确定的。文档说:

RAND() 并不是一个完美的随机生成器。这是一种按需生成随机数的快速方法,可在同一 MySQL 版本的平台之间移植。

它不能使用 /dev/random,因为 MySQL 设计用于各种操作系统,其中一些没有 /dev/random。

MySQL 在服务器启动时初始化默认种子,使用time(0). 如果您对源代码行感兴趣,它位于文件 sql/mysqld.cc, function 中的 MySQL 源代码中init_server_components()。我认为它永远不会重新播种。

然后随后的“随机”数字仅基于种子。请参阅源文件 mysys_ssl/my_rnd.cc,函数my_rnd()


随机选择任务的最佳实践解决方案,无论是性能还是随机化质量,都是在最小主键值和最大主键值之间生成一个随机值。然后使用该随机值在表中选择一个主键:

SELECT ... FROM MyTable WHERE id > $random LIMIT 1

您使用 > 而不是 = 的原因是,由于行被删除或回滚,您可能在 id 中存在间隙,或者您的 WHERE 子句中可能有其他条件,因此您在符合条件的行之间存在间隙.

这种大于方法的缺点:

  • 在这样的差距之后的行有更高的机会被选中,差距越大机会越大。
  • 在生成随机值之前,您需要知道 MIN(id) 和 MAX(id)。
  • 如果您需要多个随机行,则效果不佳。

这种方法的优点:

  • 即使对于适度的表大小,它也比 ORDER BY RAND() 快得多。
  • 您可以在 SQL 之外使用随机函数。
于 2013-04-02T14:47:49.683 回答
1

兰德是伪随机的。小心将其用于安全方面。我不认为您的“从五十个中随机选择一排”是为了安全,所以您可能没问题。

对于一张小桌子来说,这相当快。从大表中选择随机行将是可怕的:它必须用伪随机数标记每一行,然后对它们进行排序。对于您描述的应用程序,@TheEwook 的建议是完全正确的;即使是对一个小表进行超过每毫秒一次的排序也会淹没强大的 MySQL 硬件。

永远不要播种 RAND,除非你正在测试并且你想要一个可重复的随机数序列用于某种单元测试。在生成我认为难以猜测的会话令牌时,我曾经以一种艰难的方式学到了这一点。MySQL 人员在 RAND 方面做得很好,您可以信任他们的应用程序。

我认为(不确定),如果你不播种,它会从 /dev/random 中的随机种子开始。

如果您需要加密级随机数,请自行阅读 /dev/random。但请记住,/dev/random 只能生成有限的速率。/dev/urandom 使用 /dev/random 生成更快的速率,但在其熵池中没有那么高等级。

于 2013-04-02T14:31:49.570 回答
0

如果您的表不是太大(假设最多 1000 条记录),这并不重要。但是对于大桌子,您必须选择另一种方式。

这篇文章可以帮助你:

http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/

于 2013-04-02T14:23:19.697 回答