[英]MySQL select 20 random rows from 300 rows fast
我的数据库目前有300行,并且未来几年可能会增加到约5000行。 我想知道如何最好地随机选择20行。
我在这里发现MySQL从600K行中快速选择了10个随机行 (这里再次引用到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
因此,在php中,我尝试了以下操作以获得20行:
$anfrage = "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 20";
$ergebnis=$db->query($anfrage)
or die($db->error);
while($zeile=mysqli_fetch_assoc($ergebnis))print_r($zeile);
但是,当我运行脚本时,大部分时间我不会得到20行。 实际上,从300个中选择20个不同的行的概率约为48.8%。
我可以更改上面的代码以非常快地获得20行吗?
获取20个随机名称的“缓慢”方式是这样的:
SELECT name
FROM random
ORDER BY rand()
LIMIT 20;
在300行上,这可能与您使用的方法具有相似的性能。 你试过了吗? 我不确定大约5,000行,但是在那里也值得尝试。
您的方法本质上是这样(查询有点简化):
SELECT name
FROM random r1 CROSS JOIN
(SELECT RAND() * MAX(id) as id FROM random) r2
WHERE r1.id >= r2.id
ORDER BY r1.id ASC
LIMIT 20;
您假设对每个迭代使用不同的值评估r2
。 该假设可能不正确。
另一种方法是这样做:
SELECT name
FROM random r1 CROSS JOIN
(SELECT count(*) as cnt FROM random) const
WHERE rand() <= 20.0 / cnt;
不幸的是,这给出了大约的行数。 每次大约20次。 也许您真的想要20。在这种情况下,请执行以下操作:将预期的行数加倍,然后使用/ order by
limit
进行order by
:
SELECT name
FROM random r1 CROSS JOIN
(SELECT count(*) as cnt FROM random) const
WHERE rand() <= 2*20.0 / cnt
ORDER BY rand()
LIMIT 20;
您可以创建一个随机整理的表,您偶尔可以对其进行更新:
INSERT INTO random_ids
SELECT id
FROM table_name
ORDER BY RAND();
记录在您的应用程序中插入的随机值的数量; 然后使用以下命令:
SELECT * FROM table_name
INNER JOIN (SELECT id
FROM random_ids
LIMIT ?,20
) r1 ON r1.id = table_name.id;
因此,限制由您的应用程序确定为在[0, <count>)
的范围内
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.