mysql> select rand();+--------------------+| rand() |+--------------------+| 0.1689035568096708 |+--------------------+1 row in set (0.00 sec)
select title, description from film ORDER BY RAND() LIMIT 1;
- 1.创建一个临时表,临时表的字段为rand、title、description
- 2.从表中取出一行,调用RAND(),将结果和数据放入临时表,以此类推
- 3.针对临时表,将rand字段+行位置(主键)放入sort_buffer
- 4.对sort_buffer排序,取出第一个的行位置(主键),查询临时表
有点乱,看下面的例子
select title, description from film ORDER BY RAND() LIMIT 1;
- 创建一个临时表,临时表的字段为rand、title、description

- 从表(源表)中取出一行,调用RAND(),将结果和数据放入临时表,以此类推
比如有1000行表记录,得到1000行的中间结果放入临时表中
,
- 针对临时表,将rand字段+行位置(主键)放入sort_buffer

因为这个临时表可能是内存表也可能是磁盘表。
- 对sort_buffer排序,取出第一个的行位置(主键),回到临时表,查询临时表

为什么会慢?
- SQL执行过程中出现了两次中间结果,都是全长度的
- 仅需要一个随机结果,缺经历了不必要的排序(虽然优化过)
调用了很多次RAND()。
select max(film_id),min(film_id) into @M,@N from film ; set @X= floor((@M-@N+1)*rand() + @N); select title, description from film where film_id >= @X limit 1;选取数据中最大的ID和最小的ID
- 使用RAND()随机选取一个ID
-
解决方法—业务方案
查询数据表总数total
- total范围内,随机选取一个数字r
- 执行以下SQL:
select title, description from film limit r, 1;
总结
- ORDER BY RAND() limit 1 是效率很低的随机查询方式
- 原因主要是,上述方法有两次中间结果,还有排序过程
- 可以通过修改SQL,选取随机主键方式,提升性能
- 最好还是在业务中处理,尽量减少复杂SQL
