Rails 5从db获取随机记录?

Mir*_*318 6 activerecord ruby-on-rails ruby-on-rails-5

要从db获取单个随机记录,我目前正在做:

User.all.sample

但是当有100000多个用户时,只需要几秒钟就可以加载它们,只需选择一个.

从db中加载单个随机用户的最简单方法是什么?

Gan*_*esh 11

您可以尝试以下数据库独立查询:

User.find(User.pluck(:id).sample)
[DEBUG]  (36.5ms)  SELECT `users`.`id` FROM `users`
[DEBUG] User Load (0.5ms)  SELECT  `users`.* FROM `users` WHERE `users`.`id` = 58229 LIMIT 1
Run Code Online (Sandbox Code Playgroud)

这个会触发两个查询,但这个查询性能很高,因为只需37毫秒即可获得单个随机用户记录.

而以下查询大约需要624.7ms

User.order("RAND()").first
[DEBUG] User Load (624.7ms)  SELECT  `users`.* FROM `users`  ORDER BY RAND() LIMIT 1
Run Code Online (Sandbox Code Playgroud)

我已经检查了105510用户记录.

  • `User.find(User.pluck(:id).sample)` 很棒,不依赖于 DB 类型。如果有人需要多条记录,您可以向 sample 添加一个参数,例如`User.find(User.pluck(:id).sample(4))` (2认同)
  • 我不推荐任何这些。第一种解决方案将根据用户数量消耗越来越多的内存。第二种解决方案可能真的很慢,而且会消耗大量资源。根据您**真正**需要的随机类型,有很多选择。实际上,我建议尽可能避免随机化。 (2认同)
  • @AlexTatarnikov我需要来自db的随机记录,没有特殊的随机记录,只有随机记录。如果您有更有效的解决方案,请分享 (2认同)
  • @GaneshNavale 您将所有 ID 的数组加载到内存中。想象一下,您有成千上万个 ID。 (2认同)

Ahm*_*tab 9

经过大量的试验和错误后,我发现这个解决方案很有帮助并且没有错误。

Model.find(Model.ids.sample)
Run Code Online (Sandbox Code Playgroud)

Model.ids将返回数据库中所有 id 的数组。然后我们调用sample该数组上的方法,该方法将返回列表中的随机项目。


fon*_*999 5

使用PostgresqlSQLite,使用RANDOM()

User.order("RANDOM()").first
Run Code Online (Sandbox Code Playgroud)

想必同样会为工作的MySQLRAND()

User.order("RAND()").first
Run Code Online (Sandbox Code Playgroud)

  • 这是最好的答案imo。我认为 Rails 应该在 Active Record 中实现它自己的随机记录功能来隐藏它。 (3认同)
  • 太好了,有什么不会随着 db 类型而改变的吗? (2认同)

Ren*_*ves 5

您可以在表中找到最大用户 ID,并根据限制为该最大值的随机 ID 查找用户。例子:

max_id = User.order(id: :desc).limit(1).pluck(:id).first
user = User.find_by('id > ?', rand(max_id))
Run Code Online (Sandbox Code Playgroud)

这两个查询速度非常快,因为您使用主键 (id) 索引。