【发布时间】:2018-03-28 03:56:57
【问题描述】:
为了从数据库中获取一条随机记录,我目前正在做:
User.all.sample
但是当有 100000+ 用户时,加载它们需要几秒钟,只需选择一个。
从 db 加载单个随机用户的最简单方法是什么?
【问题讨论】:
标签: ruby-on-rails activerecord ruby-on-rails-5
为了从数据库中获取一条随机记录,我目前正在做:
User.all.sample
但是当有 100000+ 用户时,加载它们需要几秒钟,只需选择一个。
从 db 加载单个随机用户的最简单方法是什么?
【问题讨论】:
标签: ruby-on-rails activerecord ruby-on-rails-5
您可以尝试以下独立于数据库的查询:
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
这个会触发两个查询,但这个会提高性能,因为它只需要 37ms 即可获得单个随机用户记录。
而以下查询大约需要 624.7ms
User.order("RAND()").first
[DEBUG] User Load (624.7ms) SELECT `users`.* FROM `users` ORDER BY RAND() LIMIT 1
我已经检查了 105510 条用户记录。
【讨论】:
User.find(User.pluck(:id).sample) 很棒,不依赖于 DB 类型。如果有人需要多条记录,您可以在示例中添加一个参数,例如 User.find(User.pluck(:id).sample(4))
使用 Postgresql 或 SQLite,使用 RANDOM():
User.order("RANDOM()").first
对于带有RAND()的MySQL,大概同样适用
User.order("RAND()").first
【讨论】:
User.offset(rand(1..User.count))。我们应该跨环境使用相同的DBMS。
经过大量试验和错误后,我发现此解决方案很有帮助且无错误。
Model.find(Model.ids.sample)
Model.ids 将返回数据库中所有 id 的数组。然后我们在该数组上调用sample 方法,该方法将返回列表中的随机项。
【讨论】:
您可以在表格中找到最大用户 ID,并找到一个给定随机 ID 限制在此最大值的用户。示例:
max_id = User.order(id: :desc).limit(1).pluck(:id).first
user = User.find_by('id > ?', rand(max_id))
这两个查询非常快,因为您使用的是主键 (id) 的索引。
【讨论】:
rand() 接受一个整数
用于导轨 6
你可以通过记录数来获得你想要的记录数
User.all.sample(1)
以上查询只会返回用户的一条随机记录
【讨论】:
您可以使用 Model.all.sample.attribute 在 Rails 控制台中获取示例。
例如:
Contact.all.sample.name
=> "Bob Mcmillan"
【讨论】: