当SQL中有order by,而此时没有合适的索引可以避免排序的话,则只能选择一种排序方式,要么全字段排序,要么rowid排序,另外排序是空间的,要么使用内存临时表,要么使用文件临时表。
当SQL中除了有order by x 还有limit时,说明排序后的结果取前Y行就行了,排序所有就浪费了,那么在选择排序算法上就会选择优先队列算法,如果limit的值较大,那么堆占用的空间就太大了,就会选择归并排序。

  1. mysql> select word from words order by rand() limit 3;

内存临时表(默认使用Memory引擎)

上边这个SQL执行的时候,会使用内存临时表,通过explain命令可以看到,Using temporary,Using filesort,使用了内存表,并且需要排序,但是排序有全字段排序和rowid排序,那这个查询会使用哪个排序呢?
首先rowid排序的缺点是,多一次回表,回表造成了磁盘随机读,而内存临时表的回表根本不会造成磁盘的随机读,因此这里使用的rowid排序
image.png
image.png
可以通过OPTIMIZER_TRAC查看执行结果

  1. set tmp_table_size=1024;
  2. set sort_buffer_size=32768;
  3. set max_length_for_sort_data=16;
  4. /* 打开 optimizer_trace,只对本线程有效 */
  5. SET optimizer_trace='enabled=on';
  6. /* 执行语句 */
  7. select word from words order by rand() limit 3;
  8. /* 查看 OPTIMIZER_TRACE 输出 */
  9. SELECT * FROM `information_schema`.`OPTIMIZER_TRACE`\G

磁盘临时表

也不是所有的临时表都是内存临时表,可以通过设置tmp_table_size这个配置限制内存临时表的大小,默认值是16M。如果内存临时表的大小超过了这个值,那么内存临时表就会转换为磁盘临时表。
这里的排序就是优先队列排序和归并排序的选择了。