眾所周知,在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;