【问题标题】:How to optimize slow MySQL Query due to ORDER BY RAND()? [duplicate]由于 ORDER BY RAND(),如何优化缓慢的 MySQL 查询? [复制]
【发布时间】:2011-10-31 22:48:37
【问题描述】:

所以我有这个相对简单的查询,可以根据两个不同的 MyISAM 表中的一些条件拉随机行:

SELECT 
    table1 . * , table2 . * 
FROM 
    Table1 AS table1
LEFT JOIN 
    Table2 AS table2
USING (
    col1
)
WHERE 
    table1.col1 !=  '5324372'
AND 
    table1.col2 LIKE  'S'
AND (
    table1.col3 LIKE  'I'
    OR table1.col3 LIKE  'V-G'
)
AND (
    table2.col1 =  'A'
    OR table2.col2 =  'B'
)
ORDER BY RAND( ) 
LIMIT 1

...一开始运行良好,但随着我的数据库开始增长,现在需要几秒钟才能执行。

上面使用的所有列都有索引,所以这不是索引问题。

根据我的研究,这是由于 ORDER BY RAND() 行显然在大型表上运行非常缓慢。

我已经看到了这个问题的一些潜在解决方案,但它们非常神秘,我无法理解与上面的查询相关的任何一个。

我真的很惊讶 MySQL 没有内置的解决方案来解决这个非常慢的ORDER BY RAND() 问题,因为在我看来,对于需要选择随机行的许多类型的应用程序来说,这是一个非常基本的需求.

那么如何优化我上面的查询,以便在不长执行时间的情况下获得相同/相似的效果?

【问题讨论】:

    标签: mysql database random


    【解决方案1】:

    排序通常是 N*log(N) 操作。通常,查询计划器/生成器/优化器通过将其与索引或子查询自然产生的顺序结合起来,尽可能避免排序。随机排序不能以任何方式“优化”。解决办法:不要这样做。

    【讨论】:

    • 这个答案对我一点帮助都没有,因为我仍然需要能够为我的应用程序随机选择一行。
    【解决方案2】:

    您只选择了一行,我认为您可以通过 LIMIT 随机选择一行。示例:

    如果你有:

    SELECT * table  ORDER BY RAND( )  LIMIT 1;
    

    改成

    SELECT * table    LIMIT $randomvalue  ,$randomvalue + 1;
    

    $randomvalue 是从应用程序级别选择的随机值。

    更新:下面的答案比上面的更清楚。

    //get the total number of rows
    $result= mysql_query(" SELECT  COUNT(*) AS total FROM `table` ");
    $row = mysql_fetch_array($result);
    $total=$row['total'];
    
    
    //create random value from 1 to the total of rows 
    $randomvalue =rand(1,$total);
    
    
    //get the random row
    
    $result= mysql_query(" SELECT  * FROM `table` limit $randomvalue,1");
    

    【讨论】:

    • 我更喜欢纯 MySQL 的解决方案来解决这个问题。但是,使用您的解决方案,我将如何计算 $randomvalue 以及我将基于什么?
    • 好吧,在 1 和预期的行数之间选择一个数字似乎是合乎逻辑的。它会将您预期的复杂性降低到 O(N)。可能更多,因为您可以避免大量磁盘流量。
    • @Programmer 。我认为这不可能像 wildplasser 所说的那样。对于随机值,请确保它不超过总行数。
    • @usef_ksa:您应该编辑您的答案,使其为“LIMIT $randomvalue, 1”,并澄清 $randomvalue 仅基于查询的 COUNT(*) 减去 1。我做了那,它比 ORDER BY RAND() 工作得更快,而不必使查询复杂化。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2012-06-12
    • 2022-01-23
    • 2012-03-14
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多