17随机
order by rand() 使用内存临时表,内存临时表排序时使用rowid排序方法
内存临时表引擎 Memory
磁盘临时表引擎 InnoDB
临时表大小限制 tmp_table_size 默认16M,太大会转换成磁盘临时表
内存排序最大单行长度 max_length_for_sort_data 超过后再磁盘归并排序
随机排序方法
如果只随机选择1个值,可以怎么做呢?
暂时称作随机算法1:
- 取得这个表的主键 id 的最大值 M 和最小值 N;
- 用随机函数生成一个最大值到最小值之间的数 X = (M-N)*rand() + N;
- 取不小于 X 的第一个 ID 的行。
1 | select max(id),min(id) into @M,@N from t ; |
select count(*) into @C from t;
set @Y = floor(@C * rand());
set @sql = concat(“select * from t limit “, @Y, “,1”);
prepare stmt from @sql;
execute stmt;
DEALLOCATE prepare stmt;
MySQL 处理 limit Y,1 的做法就是按顺序一个一个地读出来,丢掉前 Y 个,然后把下一个
记录作为返回结果,因此这一步需要扫描 Y+1 行。再加上,第一步扫描的 C 行,总共需
要扫描 C+Y+1 行,执行代价比随机算法 1 的代价要高。
当然,随机算法 2 跟直接 order by rand() 比起来,执行代价还是小很多的。
# 小结
直接使用 order by rand(),这个语句需要 Using temporary 和 Using filesort,
查询的执行代价往往是比较大的。所以,在设计的时候你要量避开这种写法。