MySQL快速从300行中选择20个随机行

时间:2014-02-20 01:15:47

标签: php mysql sql select random

我的数据库目前有300行,并且在接下来的几年中可能会增加到约5000行。我想知道如何最好地随机选择20行。

我在这里找到MySQL select 10 random rows from 600K rows fast(再次提到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 行吗?

3 个答案:

答案 0 :(得分:0)

如果您阅读了问题中提及的article,您会发现有3个解决方案:

  • 多次执行查询
  • 编写正在执行查询的存储过程并将结果存储在临时表
  • 制作UNION

所有这些都在文章中解释。

答案 1 :(得分:0)

获得20个随机名称的“缓慢”方式是:

SELECT name
FROM random 
ORDER BY rand()
LIMIT 20;

在300行上,这可能与您使用的方法具有相似的性能。你试过吗?我不确定5000行,但也值得尝试。

你的方法基本上就是这个(查询有点简化):

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

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;

答案 2 :(得分:0)

您可以创建一个偶尔更新的混洗表:

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>)

范围内