让你从一个数据表中随机的选出5条数据,你会怎么写sql语句呢?
我想大部分的会这么写:
select xxx from table order by rand() limit 5;
但是我们会发现这个命令的执行速度非常慢。
用explain会发现 Extra 字段显示 Using temporary,表示的是需要使用临时表;Using filesort,表示的是需要执行排序操作。因此这个 Extra 的意思就是,需要临时表,并且需要在临时表上排序。
对于 InnoDB 表来说,执行全字段排序会减少磁盘访问,因此会被优先选择,对于内存表,回表过程只是简单地根据数据行的位置,直接访问内存得到数据,根本不会导致多访问磁盘。优化器没有了这一层顾虑,那么它会优先考虑的,就是用于排序的行越小越好了,所以,MySQL 这时就会选择 rowid 排序。(这里不懂可以去查一下)
怎么正确地随机排序呢?
取得整个表的行数,记为 C;
根据相同的随机方法得到 Y1、Y2、Y3;
再执行三个 limit Y, 1 语句得到三行数据。
mysql> select count(*) into @C from t;
set @Y1 = floor(@C * rand());
set @Y2 = floor(@C * rand());
set @Y3 = floor(@C * rand());
select * from t limit @Y1,1; //在应用代码里面取Y1、Y2、Y3值,拼出SQL后执行
select * from t limit @Y2,1;
select * from t limit @Y3,1;
代码选自极客时间