从mysql中的大表中快速选择随机行

laj*_*jos 45 mysql sql random select

从大型mysql表中选择随机行的快速方法是什么?

我在php工作,但我对任何解决方案感兴趣,即使它是用另一种语言.

ang*_*son 48

抓住所有id,从中挑选一个随机的ID,然后检索整行.

如果你知道id是连续的没有洞,你可以抓住最大值并计算一个随机id.

如果这里和那里有漏洞但主要是顺序值,并且您不关心稍微倾斜的随机性,请抓住最大值,计算一个id,然后选择id等于或高于您计算的第一行.倾斜的原因是id跟随这样的洞将被选中的机会高于跟随另​​一个id的机会.

如果您通过随机订购,那么您的手上会有一个可怕的表扫描,而快速这个词并不适用于这样的解决方案.

不要这样做,也不应该通过GUID订购,它有同样的问题.


Vin*_*vic 37

我知道必须有一种方法可以在一个查询中快速完成.这是:

一种没有外部代码参与的快速方式,值得称赞

http://jan.kneschke.de/projects/mysql/order-by-rand/

SELECT name
  FROM random AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

  • 请注意这里的权衡,为了确保在第一次尝试时获得结果,任何前面有间隙的键将更有可能被选中。例如,给定键为 1 和 10 的两条记录,以 10 作为键的记录将有 90% 的时间被选中。 (2认同)

Ces*_*arB 30

MediaWiki使用了一个有趣的技巧(对于维基百科的特殊:随机特征):带有文章的表格有一个带有随机数的额外列(在创建文章时生成).要获得一篇随机文章,请生成一个随机数,并获得随机数列中下一个更大或更小(不记得哪个)值的文章.使用索引,这可以非常快.(MediaWiki是用PHP编写的,是为MySQL开发的.)

如果结果数字分布不均,这种方法可能会导致问题; IIRC,这已在MediaWiki上修复,所以如果您决定这样做,您应该查看代码以查看它当前是如何完成的(可能它们会定期重新生成随机数列).


Bil*_*win 12

这是一个运行相当快的解决方案,它可以获得更好的随机分布,而不依赖于连续的id值或从1开始.

SET @r := (SELECT ROUND(RAND() * (SELECT COUNT(*) FROM mytable)));
SET @sql := CONCAT('SELECT * FROM mytable LIMIT ', @r, ', 1');
PREPARE stmt1 FROM @sql;
EXECUTE stmt1;
Run Code Online (Sandbox Code Playgroud)