直接使用order by rand()
比如这个语句:select word from words order by rand() limit 3;
这个语句需要Using temporary 和 Using filesort,查询代价较大:需要临时表,并且需要在临时表上排序。
- Using temoporary:表示需要使用临时表
- Using filesort:需要执行排序操作
随机排序的方法
如果只是取1个word值,如果主键id是自增主键:
- 取出最大主键M和最小主键N
- 用随机函数生成一个最大值到最小值之间的数X=N+(M-N)*rand();
- 取不小于X的第一个ID的值(为了防止缺失,所以取数逻辑是 where id >=X limit 1)
问题:ID中间可能有空洞,导致每行被选中的概率不同。比如表中id只有1,2,4,5,那么id=4这一行命中的概率是其他数字的两倍。
另外一种随机排序的方法
- 取整个表的行数,记为C。
- 取得 Y = floor(C * rand()),floor 函数在这里的作用,就是取整数部分。
- 再用 limit Y,1 取得一行。
这个随机算法,避免了上一个随机算法的概率不均匀的问题。
分析:
- 第1步获取C,需要扫描C行
- 第3步,扫描Y+1行。MySQL处理limitY,1 的做法需要按顺序一个一个读出来,丢掉前Y个,然后把下一个记录作为返回结果,因此这一步需要扫描Y+1行。
- 总共需要扫描C+Y+1行,成本比之前的随机排序算法高一些。
- 但是和order by rand()代价小很多。