【问题标题】:Selecting random row from table with 10k+ records从具有 10k+ 条记录的表中选择随机行
【发布时间】:2013-05-23 00:03:58
【问题描述】:

我目前正在编写一个网站项目,并且我有一个存储汽车信息的表格。该表有如下信息,表中有大约 20 列,我只想知道从一行中随机获取所有列数据的最快方法是什么。我知道有一个“ ORDER BY RAND() ”,但我读到它使用起来很慢,而且我担心由于表很大,这可能会导致问题,是否有替代方案。

我将在 InnoDB 中使用 MySQL,但如果使用替代数据库引擎可以更有效地选择随机行,则可以更改此设置。该网站将使用 PHP(可能是 RubyOnRails)进行编码,数据库将由一个 Python 脚本填充,该脚本将抓取汽车信息网站。

表格包含诸如

之类的行

汽车桌 -

  • 车名
  • 汽车制造商
  • 门牌号
  • ...
  • ...
  • ...

【问题讨论】:

标签: php mysql ruby-on-rails innodb


【解决方案1】:

你可以试试这个方法。

找出表的最大 id。

 SELECT id FROM car ORDER BY id DESC LIMIT 1;
 -- This result can be cached

计算最小 id(或仅 1)和最大 id 之间的 rand 值。

$rand_id = mt_rand(1, $max_id);

选择最近的行。

SELECT * FROM `car` WHERE id >= ? ORDER BY id LIMIT 1;

但如果表格有“洞”,结果就不会是“真正的随机”。但是,我认为,这对你来说是正常的。

【讨论】:

  • 我认为SELECT MAX(id) FROM car 可能是更好的选择,但如果你正在缓存它,那么问题应该不大。
  • 我认为可能发生的主要问题是,如果我有十个记录和删除记​​录7和8,并且从0到max的随机数(10)选择了7或8时会发生什么?
  • @BratislavaBob,7,8,9 将是 9。如果您需要“真正的随机”,您应该使用 Barmar 解决方案。它会比 ORDER BY RAND() 快,但比我的慢。
  • 对,这个版本会偏向紧跟在间隙之后的元素,与间隙的大小成正比。
【解决方案2】:

如果ORDER BY RAND()的性能太慢,可以通过两个查询来完成。首先,做:

SELECT COUNT(*) c FROM CarTable

然后选择一个介于 0 和c-1 之间的随机整数,在 PHP 中是:

$rownum = rand(0, $c);

然后,进行另一个查询:

SELECT * FROM CarTable
LIMIT :rownum, 1

【讨论】:

  • 此解决方案存在性能问题。但是,我认为,10k 行就可以了。
  • 应该比ORDER BY RAND()好。它是 O(n) 而不是 O(n log n)。
  • @sectus 但是 ORDER BY RAND() 更糟糕,因为它必须读取 每条 记录(不仅仅是第一个 $rownum)并且必须对它们进行排序。为了做得更好,您需要使用带有ROWNUM() 的数据库,但 MySQL 没有。
【解决方案3】:

在 Rails 中,你可以这样做:

class MyModel < ActiveRecord::Base
  def self.random_record
    find :first, offset: rand(count)
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-06-28
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    • 1970-01-01
    • 2019-07-15
    • 2016-05-06
    • 2011-09-05
    相关资源
    最近更新 更多