如何在 MySQL 中获取随机行无自动增量?

问题描述

我有一个大型数据库MysqLaurora 无服务器),我想获取随机行(例如 1 或 5) 我知道使用 SORT BY RAND() 很慢,所以放弃了。

我也知道这里有一些技巧使用行的标识符,但这仅在 id 是自动递增的整数时才有效。

就我而言,我的数据库使用 BINARY(16) 作为标识符/主键,它是随机生成的哈希。

问题是,我应该怎么做才能检索此配置的随机行?

请注意,在我的情况下,速度比准确性更重要,因此如果它不是完全随机的行,这不是大问题。

我有一些不知道是好是坏的想法:

-每次添加新行时,我还会添加一个使用 RAND() 的额外列,并使用该字段进行排序。问题是,这会一次又一次地生成相同的随机行。除非我定期更新该字段。看起来太复杂了。

-发送 2 个请求。第一个获取最旧的 createdAt 日期。然后,第二个,使用最旧的和现在之间的随机日期对其进行排序。这不是 100% 准确,因为创建日期分布不均,但正如我所说,在我的用例中,速度比准确性更重要。

-不知何故,使用我的ID,因为它们已经是随机的,也许我可以从随机位开始排序。不知道。

你怎么看?你有更多的想法吗?谢谢。

解决方法

如果您的 id 确实是随机的,您可以选择一个随机值并找到大于或等于该值的第一个 id。如果您的随机值恰好大于表中的任何 id,请重试。

理想情况下,您在代码中选择随机值,但 unhex(md5(rand())) 是一个快速的技巧,它应该生成一个随机的 16 字节字符串:

select id
from yourtable
where id >= unhex(md5(rand()))
order by id
limit 1
,

如果您的 id 分布非常均匀,您可以生成一个新的随机 id,然后执行如下查询:

SELECT * FROM mytable WHERE id > ? LIMIT 1

如果您需要多个随机行(您说的是 1 到 5 之间),则重复查询,为每次尝试生成一个新的随机 ID。

检查查询实际上返回了一行,以说明您的随机 id 大于存储在表中的最后一个 id 的情况。在这种情况下,请重试。

检查是否有重复项,如果有则重试。从 50 万行中多次选择同一行应该很少见,因此重试的开销很小。

如果您想要 N 个随机行,但表中的总行数小于 N,也存在风险。如果您的重复重试逻辑没有考虑到这一点,您可能会创建一个无限循环。

如果 id 的分布不均匀,则此技术更有可能选择前面有较大间隙的行。所以它不是一个非常准确的随机化器。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...