从大型mysql表中选择随机行的快速方法是什么?
我在php工作,但我对任何解决方案感兴趣,即使它是用另一种语言.
抓住所有id,从中挑选一个随机的ID,然后检索整行.
如果你知道id是连续的没有洞,你可以抓住最大值并计算一个随机id.
如果这里和那里有漏洞但主要是顺序值,并且您不关心稍微倾斜的随机性,请抓住最大值,计算一个id,然后选择id等于或高于您计算的第一行.倾斜的原因是id跟随这样的洞将被选中的机会高于跟随另一个id的机会.
如果您通过随机订购,那么您的手上会有一个可怕的表扫描,而快速这个词并不适用于这样的解决方案.
不要这样做,也不应该通过GUID订购,它有同样的问题.
我知道必须有一种方法可以在一个查询中快速完成.这是:
一种没有外部代码参与的快速方式,值得称赞
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;
MediaWiki使用了一个有趣的技巧(对于维基百科的特殊:随机特征):带有文章的表格有一个带有随机数的额外列(在创建文章时生成).要获得一篇随机文章,请生成一个随机数,并获得随机数列中下一个更大或更小(不记得哪个)值的文章.使用索引,这可以非常快.(MediaWiki是用PHP编写的,是为MySQL开发的.)
如果结果数字分布不均,这种方法可能会导致问题; IIRC,这已在MediaWiki上修复,所以如果您决定这样做,您应该查看代码以查看它当前是如何完成的(可能它们会定期重新生成随机数列).
这是一个运行相当快的解决方案,它可以获得更好的随机分布,而不依赖于连续的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;