【问题标题】:Rails—get a random record from db?Rails 5——从 db 中获取随机记录?
【发布时间】:2018-03-28 03:56:57
【问题描述】:

为了从数据库中获取一条随机记录,我目前正在做:

User.all.sample

但是当有 100000+ 用户时,加载它们需要几秒钟,只需选择一个。

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

【问题讨论】:

    标签: ruby-on-rails activerecord ruby-on-rails-5


    【解决方案1】:

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

    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))
    • 我不推荐这些。第一个解决方案将根据用户数量消耗越来越多的内存。第二种解决方案可能真的很慢并且还消耗大量资源。根据您真正需要的随机类型,有很多选择。其实我建议尽量避免随机化。
    • 还有什么其他有效的选择。请将它们作为答案发布,以便其他人也知道解决方案。
    • @AlexTatarnikov 我需要来自数据库的随机记录,没有特殊类型的随机,只是随机记录。如果您有更有效的解决方案,请分享
    • @GaneshNavale 您将把所有 id 的数组加载到内存中。想象一下,您有成千上万个 id。
    【解决方案2】:

    使用 PostgresqlSQLite,使用 RANDOM():

    User.order("RANDOM()").first
    

    对于带有RAND()MySQL,大​​概同样适用

    User.order("RAND()").first
    

    【讨论】:

    • 太好了,有什么不会随着 db 类型而改变的吗?
    • 是的,还有另一种解决方案,但效率较低:User.offset(rand(1..User.count))。我们应该跨环境使用相同的DBMS
    • @fongfan999 仅在您没有任何漏洞(已删除记录)时才有效。
    • 这是 imo 的最佳答案。我认为 Rails 应该在 Active Record 中实现它自己的随机记录功能来隐藏它。
    【解决方案3】:

    经过大量试验和错误后,我发现此解决方案很有帮助且无错误。

    
    Model.find(Model.ids.sample)
    

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

    【讨论】:

      【解决方案4】:

      您可以在表格中找到最大用户 ID,并找到一个给定随机 ID 限制在此最大值的用户。示例:

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

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

      【讨论】:

      • 看来你也不需要在那里采摘
      • 这个解决方案是最快的,显然在评论的那一刻被低估了
      • 这个解决方案在你使用 UUID/GUID 作为你的 id 类型时不成立,因为rand() 接受一个整数
      【解决方案5】:

      用于导轨 6

      你可以通过记录数来获得你想要的记录数

      User.all.sample(1)

      以上查询只会返回用户的一条随机记录

      【讨论】:

        【解决方案6】:

        您可以使用 Model.all.sample.attribute 在 Rails 控制台中获取示例。

        例如:

        Contact.all.sample.name
        => "Bob Mcmillan"
        

        【讨论】:

          猜你喜欢
          • 2011-07-17
          • 1970-01-01
          • 2015-05-05
          • 2014-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-03-30
          相关资源
          最近更新 更多