mysql优化--rand()优化
众所周知,在mysql中,随机的取10条数据,如:select * from users order by rand() limit 10,效果非常差,因为会多次的执行,如果等值查询用rand()也是效很差,
1.select id from users where id =111;
看查询计划可以得到,是是常量查询,而且是索引覆盖,速度非常快!
2.使用rand(),求随机数后检索
select id from users where id=round(rand()*1000);
执行计划很糟糕,虽然是扫描了索引,但是是全索引的扫描,很差,因为where条件中包含了rand(),使得mysql把它当做变量来处理。无法用常量的等值查询。
3.改造成普通的子查询
select id from users where id =(select round(rand()*(select max(id) from users)) as nid)
查询计划也不好!(子查询会全表扫描)
4.改成join联表
select id from users as us inner join (select round(rand()*1000) as id2) as t2 on t2.id2=us.id
这样的执行计划就很好了,速度也很快
小结:从数据库随机的取一条数据时候,可以把rand()生成的随机数放到join中提高效率。
5.order by rand() limit n
随机取多条的时候
全索引扫描,生成排序临时表,文件排序,很慢!
6.仿照join方式
select id from users as us inner join (select round(rand()*(select max(id) from users)) as ids) as t1 on us.id>t1.ids limit n
全索引检索,发现符合记录的条件后,直接取10行,这个方法是最快的。
PS:综上:
想从mysql数据库里随机的取一条或者多条时,最好把rand生成的随机数放到join子句中,提高查询效率。
就是把这个sql:
select id from table order by rand() limit n;
变成这个sql:
select id from table t1 join (select round(rand()*(select max(id ) from table)) as idd) as t2 on t1.id>t2.idd limit n;