日常的开发中,总是会碰到排序的需求, 一般的排序都是使用Order By 的语句的,但是order by 语句的作用机制是怎样的呢?
Explain查看排序的语句的执行情况
Extra 这个字段中的“Using filesort”表示的就是需要排序,MySQL 会给每个线程分配一块内存用于排序,称为 sort_buffer。 看到使用id的时候,并没有使用Using filesort, 这是因为 Id字段本来就是有序的,取出的数据本身就是有序的,不用在排序了, 而使用Name字段排序就需要使用sort_buffer了。
全部字段参与排序的流程
- 先根据查询语句查询出来符合符合的记录, 把记录放入到sort_buffer内存空间中
- 对于sort_buffer中的记录进行按照条件快速排序,
- 如果sort_buffer装不下所有的记录会创建临时文件来装载记录。
- 使用了临时文件会使用归并排序来进行排序的, (确实归并排序最符合这种情况)
- 排序完成后返回符合要求的记录
sort_buffer的大小是可以设置大小的, 如果sort_buffer大小够用,就不会使用临时文件来辅助排序了。
rowid 排序
如果一行记录很大,比如包含Text类型的字段, 这个时候全部放入sort_buffer空间就很不划算了, 这个时候mysql会进行优化, 比如按照Name字段排序, 这个时候只会取得Name字段和Id字段两个字段的数据放入sort_buffer中排序, 排序完成后要返回完整的记录的时候,在根据id回表来获取完整记录。
mysql会根据每行记录的具体长度来决定是全部放入sort_buffer还是只放排序字段。 这个具体长度的值是可以设置的, SETmax_length_for_sort_data =16; 就是设置长度超过16后就不放入完整字段了
两种排序对比
- 全字段排序是内存够用的情况下采取的排序方式, 内存够用就会减少回表操作。
- 如果内存不够大, 就会使用临时文件来排序,
mysql的设计思想就是 内存够用就尽量使用内存, 减少磁盘的使用。 mysql的会尽量避免磁盘读的。
是否所有的排序都需要使用sort_Buffer
并不是所有的排序都要使用这个的, 如果从表中取得的数据本身就是符合的排序要求的就没有必要使用这个排序内存。
如果我们对于某几个字段经常进行排序查询, 可以使用覆盖索引,保证覆盖索引的顺序是符合要求的,那么排序的时候就没有必要再使用sort_buffer了。