在筛选的GROUP BY查询上优化MySQL ORDER BY RAND(),以避免临时/无索引联接

在筛选的GROUP BY查询上优化MySQL ORDER BY RAND(),以避免临时/无索引联接,mysql,sql,performance,Mysql,Sql,Performance,MySQL“join With index”计数器正在递增,如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.pr

MySQL“join With index”计数器正在递增,如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”子查询中的限制

解释/描述看起来像这样

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

虽然你们中的一些人可能会认为“如果它执行一个无索引的连接会怎么样”,也许这比可能是一个问题更令人烦恼,但我知道可能有更好的方法来实现所需的功能,尤其是在表行数增加的情况下


欢迎有任何想法

通常,运行多个查询要比按
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
)

顺便说一下,您的子查询只返回一个字段,因此您可以在操作符中使用
=
而不是

通常,运行多个查询要比按
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
)

顺便说一下,子查询只返回一个字段,因此您可以使用
=
而不是
运算符中的

限制计数-1,1
不起作用。你的意思是
limit{$count-1},1
@Johan这只是一个解释这个想法的例子。我不知道OP使用哪种编程语言:)谢谢。。。最后我把它变成了三个问题。。。查询以获取计数,确定0和计数-1之间的随机数,查询以获取随机产品的prodid,最后查询以使用group by…进行连接。。。。不得不使用第二个查询,因为出于某种非常奇怪的原因,对id执行子查询而不是单独的第二个查询会导致0返回数据,这非常奇怪。@KeithHall我认为您可以在两个查询中执行此操作。我已经编辑了我的答案。
限制计数-1,1
不起作用。你的意思是
limit{$count-1},1
@Johan这只是一个解释这个想法的例子。我不知道OP使用哪种编程语言:)谢谢。。。最后我把它变成了三个问题。。。查询以获取计数,确定0和计数-1之间的随机数,查询以获取随机产品的prodid,最后查询以使用group by…进行连接。。。。不得不使用第二个查询,因为出于某种非常奇怪的原因,对id执行子查询而不是单独的第二个查询会导致0返回数据,这非常奇怪。@KeithHall我认为您可以在两个查询中执行此操作。我对我的答案稍加修改。