我如何才能最好地编写一个查询,从总共600k中随机选择10行?


当前回答

它是非常简单的单行查询。

SELECT * FROM Table_Name ORDER BY RAND() LIMIT 0,10;

其他回答

我知道这不是你想要的,但我将给你的答案是我在一个小网站的生产中使用的。

根据您访问随机值的次数,不值得使用MySQL,因为您将无法缓存答案。我们在那里有一个按钮来访问一个随机页面,用户可以每分钟点击几次,如果他愿意的话。这将导致MySQL的大量使用,至少对我来说,MySQL是优化的最大问题。

我会采用另一种方法,你可以把答案存储在缓存中。调用MySQL:

SELECT min(id) as min, max(id) as max FROM your_table

使用min和max Id,您可以在服务器中计算一个随机数。在python中:

random.randint(min, max)

然后,用你的随机数,你可以在你的表中得到一个随机Id:

SELECT * 
FROM your_table 
WHERE id >= %s 
ORDER BY id ASC 
LIMIT 1

在这种方法中,对数据库执行两次调用,但是可以缓存它们,并且在很长一段时间内不访问数据库,从而提高性能。注意,如果表中有洞,这不是随机的。有超过一行很容易,因为你可以使用python创建Id,并为每行执行一个请求,但由于它们是缓存的,这是可以的。

如果你的表中有太多的洞,你可以尝试同样的方法,但是现在是记录的总数:

SELECT COUNT(*) as total FROM your_table

然后在python中你可以这样写:

random.randint(0, total)

为了获取一个随机结果,你可以使用如下所示的LIMIT:

SELECT * 
FROM your_table 
ORDER BY id ASC 
LIMIT %s, 1

注意它会在X个随机行之后得到1个值。即使您的表中有洞,它也将是完全随机的,但它将为您的数据库带来更多的开销。

我得到了快速查询(大约0.5秒),cpu很慢,在一个400K寄存器的MySQL数据库中随机选择10行,非缓存2Gb大小。在MySQL中快速选择随机行

$time= microtime_float();

$sql='SELECT COUNT(*) FROM pages';
$rquery= BD_Ejecutar($sql);
list($num_records)=mysql_fetch_row($rquery);
mysql_free_result($rquery);

$sql="SELECT id FROM pages WHERE RAND()*$num_records<20
   ORDER BY RAND() LIMIT 0,10";
$rquery= BD_Ejecutar($sql);
while(list($id)=mysql_fetch_row($rquery)){
    if($id_in) $id_in.=",$id";
    else $id_in="$id";
}
mysql_free_result($rquery);

$sql="SELECT id,url FROM pages WHERE id IN($id_in)";
$rquery= BD_Ejecutar($sql);
while(list($id,$url)=mysql_fetch_row($rquery)){
    logger("$id, $url",1);
}
mysql_free_result($rquery);

$time= microtime_float()-$time;

logger("num_records=$num_records",1);
logger("$id_in",1);
logger("Time elapsed: <b>$time segundos</b>",1);

我看了所有的答案,我认为没有人提到这种可能性,我也不知道为什么。

如果你想要最大限度的简单和速度,在一个较小的成本,那么对我来说,它似乎是有意义的存储在DB中的每一行的随机数。只需要创建一个额外的列random_number,并将其默认值设置为RAND()。在此列上创建索引。

然后,当您想检索一行时,在代码(PHP、Perl等)中生成一个随机数,并将其与列进行比较。

SELECT FROM tbl WHERE random_number >= :random LIMIT 1

我想虽然它对于单行来说非常整洁,但是对于像OP要求的十行,你必须分别调用它十次(或者想出一个我立即逃脱的聪明的调整)

从书中:

使用偏移量选择随机行

这是另一种避免前面提到的问题的技术 替代方法是统计数据集中的行数并返回一个随机值 0到计数之间的数字。然后用这个数字作为抵消 查询数据集时

$rand = "SELECT ROUND(RAND() * (SELECT COUNT(*) FROM Bugs))";
$offset = $pdo->query($rand)->fetch(PDO::FETCH_ASSOC);
$sql = "SELECT * FROM Bugs LIMIT 1 OFFSET :offset";
$stmt = $pdo->prepare($sql);
$stmt->execute( $offset );
$rand_bug = $stmt->fetch();

在不能假定连续键值和时使用此解决方案 您需要确保每一行都有均等的机会被选中。

它是非常简单的单行查询。

SELECT * FROM Table_Name ORDER BY RAND() LIMIT 0,10;