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处理一些较大的文件时,可能处理速度会比较慢,但却 ...
随机推荐
- jsp中如何使用Ueditor
在jsp页面中类似word编辑器操作textarea 使用步骤: step1.官网下载Ueditor http://ueditor.baidu.com/website/download.html ...
- js判断超过几个字符后显示省略号
- cf1182D Complete Mirror
可以得到一个结论, 可行的点要么是直径端点, 要么是直径中点, 要么是直径中点引出的链中最短的端点 #include<cstdio> #include<algorithm> # ...
- 关于对pei
我现在才开始整理这个不算晚吧...... 望轻喷 学习博客 我们需要四个程序 1.暴力 2.“正解” 3.数据生成器 4.检查程序 暴力: 就是暴力 eg: #include <cstdio&g ...
- 日常歌颂zyj
今年的中秋节... 我貌似遇到了一个灰常 灰常灰常优秀的 大哥哥~~ (貌似是条高二狗) 最开始在贴吧颓废... 然后... 开始逐条的回复... 开始去,,, 逐步查看,,, 发现这个优秀的楼主会 ...
- [LeetCode] 560. Subarray Sum Equals K 子数组和为K
Given an array of integers and an integer k, you need to find the total number of continuous subarra ...
- [LeetCode] 6. ZigZag Conversion 之字型转换字符串
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...
- vue图片放大、缩小、旋转等
用于图片浏览的Vue组件,支持旋转.缩放.翻转等操作,基于viewer.js. 效果: 安装 使用npm命令安装 npm install v-viewer 使用 引入v-viewer及必需的css样式 ...
- ios 信任自签名证书
1. 通过html 网络地址的方式(eg. <a href="172.26.167.82.crt">证书安装</a>)[或者通过邮件附件的方式]2. 设置- ...
- JVM系列之六:内存溢出、内存泄漏 和 栈溢出
1. OOM && SOF OutOfMemoryError异常: 除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError(OOM)异常的可能, 内存 ...