在筛选的GROUP BY查询上优化MySQL ORDER BY RAND(),以避免临时/无索引联接
MySQL“join With index”计数器正在递增,如MySQL-tuner.pl等各种分析工具所示,在跟踪到一个使用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
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我认为您可以在两个查询中执行此操作。我对我的答案稍加修改。