我有一个只有几行的表(前 50 行),我需要从表中获取随机值,我可以通过以下方式做到这一点
ORDER BY RAND() LIMIT 1
主要问题是,当我在 5 秒内进行 6k 选择时,rand 仍然“可靠”吗?
兰特是如何计算的,我可以随着时间的推移播种它吗? (我不知道,每 5 秒一次)。
MySQL 伪随机数生成器是完全确定性的。文档说:
RAND() 并不意味着是一个完美的随机生成器。这是一种按需生成随机数的快速方法,可在相同 MySQL 版本的平台之间移植。
它不能使用 /dev/random,因为 MySQL 被设计为在各种操作系统上运行,其中一些操作系统没有 /dev/random。
MySQL 在服务器启动时使用返回的整数初始化默认种子time(0)
。
如果您对源代码行感兴趣,它位于文件 sql/mysqld.cc 中的 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 之外使用随机函数。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)