在过滤的GROUP BY查询上优化MySQL ORDER BY RAND()以避免临时/无索引连接

时间:2011-09-24 12:00:10

标签: mysql sql performance

MySQL“无索引连接”计数器正在递增,如mysql-tuner.pl等各种分析工具所示,跟踪到使用RAND()选择随机产品的查询,我想优化以帮助避免这个增量。

查询如下所示:

select p.*, count(u.prodid) as count from prods p 
left outer join usage u on p.prodid=u.prodid 
where p.ownerid>0 and p.active=1
group by p.prodid
order by rand() limit 1;

我也尝试过使用这种风格......

select p.*, count(u.prodid) as count from prods p
left outer join usage u on p.prodid=u.prodid
where prodid in 
(select prodid from prods 
where ownerid>0 and active=1 
group by prodid order by rand() limit 1);

但MySQL不支持'in'子查询中的LIMIT ...

解释/描述看起来像这样......

+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                        |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+
|  1 | SIMPLE      | p     | range | ownerid       | ownerid | 4       | NULL |   11 | Using where; Using temporary; Using filesort | 
|  1 | SIMPLE      | u     | index | NULL          | userid  | 8       | NULL |   52 | Using index                                  | 
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------+

2行(0.00秒)

虽然你们中的一些人可能会认为“如果它执行无索引连接会怎么样”,也许这可能比一个问题更令人烦恼,但我很欣赏可能有更好的方法来实现所需要的东西。特别是当表行计数增长时......

所以欢迎任何想法!

1 个答案:

答案 0 :(得分:1)

通常运行多个查询比通过rand()对表进行排序更快。首先得到行的随机数:

select floor( count(*) * rand() ) random_number
from prods
where ownerid > 0 and active = 1

然后得到特定的行:

select p.*, count(u.prodid) as count 
from prods p
left outer join usage u on p.prodid = u.prodid
where prodid = (
    select prodid from prods 
    where ownerid > 0 and active = 1 
    limit {$random_number}, 1
)

顺便说一下,子查询只返回一个字段,因此您可以使用=代替in运算符。