MySQL Execution Plan--文件排序(file sort)
在MySQL处理ORDER BY语句时,如果查询无法利用索引的有序性,则需要额外操作对数据进行排序。
在MySQL中有三种排序算法:
1、快速排序(Quick Sort),对冒泡排序的一种改进,基本思想是选取一个记录作为枢轴,经过一趟排序,将整段序列分为两个部分,其中一部分的值都小于枢轴,另一部分都大于枢轴。然后继续对这两部分继续进行排序,从而使整个序列达到有序。
2、快速排序(Quick Sort),利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
3、堆排序是利用堆的数据结构实现的排序算法,通过调整二叉树上父节点和左右子节点的位置,最终得到一个有序序列.
在MySQL中有三种数据排序方式:
1、常规排序(双路排序)
2、优化排序(单路排序)
3、堆排序
堆排序在MySQL 5.6版本中引入,对于LIMIT M OFFSET N操作,仅需要排出M+N条记录,因此可以利用"大顶堆"或"小顶堆"两种堆排序算法来优化,避免对全部记录排序的资源消耗。
常规排序和优化排序都是采用分治(divide-and-conquer)策略将记录拆分为多个记录块,对每个记录块采用"快速排序"算法进行排序,再将排序后的记录块采用"归并排序"算法进行合并。
由于常规排序和优化排序都需要使用"临时文件"来存放中间排序结果,因此被称为文件排序(FileSort)。
当查询计划的extra部分显示"Using filesort"时表明该查询使用"常规排序"或"优化排序",但不表示一定会造成IO操作,只有当"中间结果集"较大时才会将"中间结果集"写入到磁盘。
相关参数:
1、参数max_length_for_sort_data用于决定FileSort采用常规排序还是优化排序,该参数在MySQL 8.0.20版本中被弃用。
2、参数sort_buffer_size用于控制每次快速排序的buffer大小,默认值为256KB,增大该值有利于减少"归并排序"操作次数和"临时文件"写入磁盘次数。
A) 在MySQL 5.7及之前版本中,会直接分配参数sort_buffer_size指定的内存,因此参数sort_buffer_size值不能设置过大。
B) 在MySQL 8.0.12版本中对参数sort_buffer_size进行优化,会根据实际需要增量分配内存,因此参数sort_buffer_size值能设置相对较大些。
3、参数read_rnd_buffer_size用于控制常规排序中需要随机读缓存大小,默认值为256KB,增大该值有利于增大"合并随机读概率"和降低"随机读"IO次数。
4、参数tmp_dir用于控制临时文件的存储位置,将tmp_dir指向多块磁盘或将tmp_dir指向高速磁盘能有效降低IO响应时间,提升排序效率。
MySQL官方文档How MySQL Does Sorting (filesort)
MySQL has two filesort algorithms for sorting and retrieving results. The original method uses only the ORDER BY columns. The modified method uses not just the ORDER BY columns, but all the columns used in the query. The optimizer selects which filesort algorithm to use. Prior to MySQL 4.1, it uses the original algorithm. As of MySQL 4.1, it normally uses the modified algorithm except when BLOB or TEXT columns are involved, in which case it uses the original algorithm. The original filesort algorithm works as follows: Read all rows according to key or by table scanning. Rows that do not match the WHERE clause are skipped.
For each row, store a pair of values in a buffer (the sort key and the row pointer). The size of the buffer is the value of the sort_buffer_size system variable.
When the buffer gets full, run a qsort (quicksort) on it and store the result in a temporary file. Save a pointer to the sorted block. (If all pairs fit into the sort buffer, no temporary file is created.)
Repeat the preceding steps until all rows have been read.
Do a multi-merge of up to MERGEBUFF (7) regions to one block in another temporary file. Repeat until all blocks from the first file are in the second file.
Repeat the following until there are fewer than MERGEBUFF2 (15) blocks left.
On the last multi-merge, only the pointer to the row (the last part of the sort key) is written to a result file.
Read the rows in sorted order by using the row pointers in the result file. To optimize this, we read in a big block of row pointers, sort them, and use them to read the rows in sorted order into a row buffer. The size of the buffer is the value of the read_rnd_buffer_size system variable. The code for this step is in the sql/records.cc source file. One problem with this approach is that it reads rows twice: One time when evaluating the WHERE clause, and again after sorting the pair values. And even if the rows were accessed successively the first time (for example, if a table scan is done), the second time they are accessed randomly. (The sort keys are ordered, but the row positions are not.) The modified filesort algorithm incorporates an optimization such that it records not only the sort key value and row position, but also the columns required for the query. This avoids reading the rows twice. The modified filesort algorithm works like this: Read the rows that match the WHERE clause.
For each row, record a tuple of values consisting of the sort key value and row position, and also the columns required for the query.
Sort the tuples by sort key value
Retrieve the rows in sorted order, but read the required columns directly from the sorted tuples rather than by accessing the table a second time. Using the modified filesort algorithm, the tuples are longer than the pairs used in the original method, and fewer of them fit in the sort buffer (the size of which is given by sort_buffer_size). As a result, it is possible for the extra I/O to make the modified approach slower, not faster. To avoid a slowdown, the optimization is used only if the total size of the extra columns in the sort tuple does not exceed the value of the max_length_for_sort_data system variable. (A symptom of setting the value of this variable too high is that you should see high disk activity and low CPU activity.)
参考资料:
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_sort_buffer_size
https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_read_rnd_buffer_size
https://dev.mysql.com/doc/refman/8.0/en/order-by-optimization.html
MySQL Execution Plan--文件排序(file sort)的更多相关文章
- Linux文件排序工具 sort 命令详解
sort是排序工具,它完美贯彻了Unix哲学:"只做一件事,并做到完美".它的排序功能极强.极完整,只要文件中的数据足够规则,它几乎可以排出所有想要的排序结果,是一个非常优质的工具 ...
- mysql中的文件排序(filesort)
在MySQL中的ORDER BY有两种排序实现方式: 1. 利用有序索引获取有序数据 2. 文件排序 在explain中分析查询的时候,利用有序索引获取有序数据显示Using index ,文件排序显 ...
- MySQL Execution Plan--数据排序操作
MySQL数据排序 MySQL中对数据进行排序有三种方式:1.常规排序(双路排序)2.优化排序(单路排序)3.优先队列排序 优先队列排序使用对排序算法,利用堆数据结构在所有数据中取出前N条记录. 常规 ...
- mysql什么时候会发生file sort
看了网上很多排名很靠前的博客,发现好多都讲错了!我开始按照博客来,没有怀疑,直到自己试了一下才发现是错的. file sort在面试中有时候会问到,这个其实挺能区分是不是真的了解order by的执行 ...
- MYSQL 磁盘临时表和文件排序
因为Memory引擎不支持BOLB和TEXT类型,所以,如果查询使用了BLOB或TEXT列并且需要使用隐式临时表,将不得不使用MyISAM磁盘临时表,即使只有几行数据也是如此. 这会导致严重的性能开销 ...
- mysql查询优化--临时表和文件排序(Using temporary; Using filesort问题解决)
先看一段sql: <span style="font-size:18px;">SELECT * FROM rank_user AS rankUser LEFT JOIN ...
- MySQL Error Log 文件丢失导致The server quit without updating PID file启动失败的场景
今天在做mysql sniff测试的时候,中间重启MySQL实例的过程中,出现了"The server quit without updating PID file"这个经典的错误 ...
- Oracle SQL explain/execution Plan
From http://blog.csdn.net/wujiandao/article/details/6621073 1. Four ways to get execution plan(anyti ...
- 排序命令sort
Unix和Linux自带的sort命令功能非常强大,其主要功能是对文本内容按不同的方法排序.它不仅可以按一个或多个字段排序,还可以合并文件.使用sort处理一些较大的文件时,可能处理速度会比较慢,但却 ...
随机推荐
- WordCount-JAVA版
WordCountMapper import java.io.IOException; import org.apache.hadoop.io.IntWritable; import org.apac ...
- [LeetCode] 891. Sum of Subsequence Widths 子序列宽度之和
Given an array of integers A, consider all non-empty subsequences of A. For any sequence S, let the ...
- Jena Fuseki安装完成后不能添加数据库
问题描述:安装Jena成功后可以进入管理页面,无法通过界面选择和查询数据 解决方案: 进入 apache-jena-fuseki-3.12.0\run 修改 shiro.ini 配置文件 注释 /$/ ...
- DingTalk钉钉消息推送(.net core 3 WebApi尝鲜记)
我发了个朋友圈,Swagger真他妈的牛B,解放了开发API的码农,麻麻再也不用担心我们写API文档耽误回家吃饭了. /// <summary> /// 发送钉钉消息 /// </s ...
- (十四)golang--函数和包
1.怎么定义函数? func (形参列表) 返回值列表{ 执行操作 return } 2.什么是包? 包的本质就是一个文件夹,存放程序文件 三大作用: 区分相同的名字的函数.变量等标识符: 当程序文件 ...
- HTTP之URL的快捷方式
URL快捷方式 ==================摘自<HTTP权威指南>======================= WEB客户端可以理解并使用几种URL快捷方式.相对URL是在某职 ...
- Mybatis成为Java互联网时代首选持久框架的原因
持久层可以将业务数据存储到磁盘,具备长期存储能力,只要磁盘不损坏(大部分的重要数据都会有相关的备份机制),在断电或者其他情况下,重新开启系统仍然可以读取这些数据.一般执行持久任务的都是数据库系统.持久 ...
- RGB灯
robotbit扩展板4个rgb灯,r-红,g-绿,b-蓝,值为0~255,可模拟出256*256*256种颜色. from microbit import * import neopixel r = ...
- git 版本(commit) 回退 -- 使用git reset 指令
刚刚提交了三个commit, git reflog显示如下: 最后一个commit在文件末尾加了一行:v3,以此类推: 下面,使用git reset --hard commitID来进行commit回 ...
- IScroll Unable to preventDefault inside passive event listener due to target being treated as passive
最近两天企业微信下IScroll突然无法滚动了,特别慢,之前好好的,发现主要是有红色的Unable to preventDefault inside passive event listener du ...