我的编程空间,编程开发者的网络收藏夹
学习永远不晚

浅谈Usingfilesort和Usingtemporary为什么这么慢

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

浅谈Usingfilesort和Usingtemporary为什么这么慢

1.简介

我们都知道使用explain 分析sql语句的时候,如果,在Extra这一列发现Using index说明使用了覆盖索引,没有回表操作性能还不错;那么,如果发现是Using filesortUsing temporary 出现了文件排序,临时表, 这个时候,我们就需要进行索引优化了;那么,问题来了,我们需要怎么优化呢?为什么出现这两个的时候,Mysql是怎么执行的呢?效率怎么就低下呢?所以,如果不知道它的执行原理的话,其实,我们也无法进行针对性的优化;所以,本文主要就是探讨一下Mysql 出现Using filesortUsing temporary时的场景和优化方法;

2.Using filesort

Using filesort: 文件排序;我们首先来模拟一下文件排序,然后再分析一下为什么文件排序效率较低;最后,在来说一下解决方案;

2.1 Using filesort 现象模拟

建表语句

CREATE table study (
	id int(11) not null,
	name varchar(32) DEFAULT NULL,
	score int(11) DEFAULT NULL,
	PRIMARY key (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

现在,有一个需求需要把所有的同学都找出来,然后,按照成绩从高到低进行排序;很显然,sql语句可以这么写:

select id, name, score FROM study order by score DESC;

然后,我们对这个sql语句使用explain进行分析:

分析结果如下:使用的是全表扫描,在扫描的过程中,出现了Using filesort文件排序;很显然,对于文件排序我们需要进行优化;

2.2 Using filesort 之Mysql的执行过程

Using filesort 文件排序,其实文件排序的话,会有很多种情况,比如说:根据要排序的内容大小,就有内部排序外部排序;如果,排序的内容比较小,那么,在内存中就可以搞定,这就是内部排序(使用快排);如果,要排序的内容太大,那么,就得需要通过磁盘的帮助了,这个就是外部排序(使用归并)。
还有,就是根据一行的大小来进行区分,如果,一行的内容不是很大,那么,就整个字段读取出来进行排序,称为全字段排序;如果,整个字段内容很大,那么,就采用rowid排序,读取rowid和该字段先进行排序,然后,再回表查找其他的内容; 下面,我将分别解释在全字段排序和rowid排序的时候,这个sql的执行过程;

2.2.1 全字段排序

sql执行过程

  • 初始化sort_buffer,确定要放入的是id,name,score这三个字段
  • 全表扫描,取出id, name, score这三个字段的值,存入到sort_buffer中;
  • 对sort_buffer中的数据按照字段score做快速排序(在这里产生了filesort);
  • 将排序完的结果进行返回即可

注意:第三步可能是在内存中完成,但是,如果内存中排序数据量太大,内存放不下,则不得不利用磁盘临时文件辅助排序,如果,内存放不下的话,使用的就是外部排序,(将快排的结果写入到临时文件中)外部排序使用的是归并排序;(两个有序文件使用归并排序,时间复杂度为N效率较高)
总结:针对,Using filesort的全字段排序,使用快排时间复杂度为NlogN。所以,效率较低;应该避免。

2.2.2 rowid排序

rowid:一张表中如果没有主键或者非空唯一索引时,就会创建一个rowid大小为6字节;
产生背景: 在我们排序的过程中,因为,sort_buffer是有限的,如果,我们要查询的字段很多的话,那么,sort_buffer里面要放的字段数太多,这样内存能够同时放下的行数就会很少,就需要分成多个临时文件,再进行归并,排序的性能会很差;
为了解决这个问题,Mysql会进行优化,如果,一行数据大于一个阈值的话,读入到内存的时候,就是读取rowid + 要排序的字段;然后,再通过rowid回表去查询剩余的字段;我们通过SHOW VARIABLES LIKE '%max_length_for_sort_data%';这个指令可以查看这个阈值;
使用rowid的sql执行过程

  • 初始化sort_buffer,确定要放入的字段为 id, 和 score;
  • 全表扫描,取出id, score这两个字段的值,存入到sort_buffer中;
  • 对sort_buffer中的数据按照字段score做快速排序(如果,数据太多,可能会导致外部文件排序);
  • 所有数据排序好以后,根据id回表查询name字段的内容;
  • 把所有的数据返回给客户端

2.3 解决方案

针对,这个题目来说,解决方案也是比较简单的;要查询的字段是id , name, score;然后,需要对score进行排序。可以对score + name 建立联合索引,id是主键,这样,这三个字段都在普通索引中能够查询到,就解决了文件排序,也使用了覆盖索引;

create index index_score_name on study(score, name);

explain分析:

type = index 表示基于索引列的扫描;Extra = Using index 表示覆盖索引 Extra = Backward index scan;表示基于索引从后往前找;效果较佳;经过测试,使用索引,以空间换时间,把数据提交按照score排好序,符合我们的需求;

3.Using temporary

背景Mysql 执行查询语句时,对于order by 可能会导致filesort或者temporary。
原则:filesort只能应用于单个表上,如果,有多个表的数据需要进行排序,那么,Mysql会先创建一张临时表来保存数据,然后,再在临时表上使用filesort进行排序,最后输出结果。

3.1 场景再现

建表语句:

create table t1(    
id int, col1 int, col2 varchar(10),
key(id, col1));
create table t2(
id int, col1 int, col2 varchar(10),
key(col1));

情况一:

explain select * from t1 force index(id), t2 where t1.id=1 and t1.col1 = t2.col2 order by t1.col1;

这边,即没有使用temporary 也没有使用filesort。
那么,它是怎么执行的呢?
它其实是先定位t1.id;然后,定位t1.col1;这两个都是通过索引来进行;然后,在执行和t2表的联结(where)所以,没有文件排序和临时表;
情况二:

explain select * from t1 force index(id), t2 where t1.id=1 and t1.col1 = t2.col2 order by t1.col2;

这里是产生了filesort;执行过程如下:

  • 根据先定位t1.id;
  • 把id=1的都取出来,把所有的字段也都取出来;存到sort_buffer中。
  • 存入sort_buffer之后,需要根据t1的字段col2进行排序;
  • t1表排序好了后,根据排序好的结果集去联结t2表中的数据;(所以,没有产生临时文件)

情况三:

explain select * from t1 force index(id), t2 where t1.id=1 and t1.col1 = t2.col2 order by t2.col1 ;

这里,产生了temporary 和 filesort;执行过程如下:

  • 根据id索引先定位t1.id = 1所在行;
  • 由于order by的字段是在t2表上;所以,这个时候,不能排好序后再去联结t2表了;
  • 需要把t1 和 t2表先联结起来,保存到temporary表上,然后,再根据t2.col1字段进行filesort;所以效率是很慢的;

3.2 解决方案

通过,对temporary的分析,如果,要排序的字段在主表上,是不会产生temporary的;所以,如果可以的话,我们尽量修改sql语句 把要排序字段放在主表中;或者使用straight_join(强制把左边的表设置为驱动表); 针对情况三sql重写

select * from t2 force index(col1)  straight_join t1  on t1.id=1 and t1.col1 = t2.col2 order by t2.col1 ;

explain分析如下:

4.总结

本文主要是根据个人写了filesort、temporary 产生原因,处理方式;在处理方案上,可能考虑不足,如果,有一些其他的产生原因或者处理方案。欢迎交流;

到此这篇关于浅谈Using filesort和Using temporary 为什么这么慢的文章就介绍到这了,更多相关Using filesort Using temporary内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

浅谈Usingfilesort和Usingtemporary为什么这么慢

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python为什么这么慢

本篇内容介绍了“Python为什么这么慢”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Python 现在越来越火,已经迅速扩张到包括 Dev
2023-06-17

浅谈Java为什么只能单继承

本文主要介绍了Java为什么只能单继承,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-03-15

浅谈MySQL为什么会选错索引

目录1.引例2.优化器的逻辑3.解决办法1.引例首先创建一张表,并对字段a,b分别建立索引:create table t (id int(11) not null,a int(11) default null,b int(11) def
2023-03-20

浅谈为什么MySQL不推荐使用子查询和join

做分页查询:1.对于mysql,不推荐使用子查询和join是因为本身join的效率就是硬伤,一旦数据量很大效率就很难保证,强烈推荐分别根据索引单表取数据,然后在程序里面做join,merge数据。 2.子查询就更别用了,效率太差,执行子查询
2022-05-29

浅谈python为什么不需要三目运算符和switch

对于三目运算符(ternary operator),python可以用conditional expressions来替代 如对于x<51:0可以用下面的方式来实现1if x<5else 0注: conditional expression
2022-06-04

Mysql性能优化:为什么你的count(*)这么慢?

导读在开发中一定会用到统计一张表的行数,比如一个交易系统,老板会让你每天生成一个报表,这些统计信息少不了 sql 中的count函数。但是随着记录越来越多,查询的速度会越来越慢,为什么会这样呢?Mysql内部到底是怎么处理的?今天这篇文章将从Mysql内部对于
Mysql性能优化:为什么你的count(*)这么慢?
2017-03-10

浅谈Thread.sleep()为什么要抛出中断异常

本文主要介绍了浅谈Thread.sleep()为什么要抛出中断异常,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-05-17

一文解答为什么MySQL的count()方法这么慢

目录前言count()的原理各种count()方法的原理允许粗略估计行数的场景必须精确估计行数的场景总结前言mysql用count方法查全表数据,在不同的存储引擎里实现不同,myisam有专门字段记录全表的行数,直接读这个字段就好了。而i
2022-07-01

浅谈为什么MySQL不建议delete删除数据

前言我负责的有几个系统随着业务量的增长,存储在MySQL中的数据日益剧增,我当时就想现在的业务方不讲武德,搞偷袭,趁我没反应过来把很多表,很快,很快啊都打到了亿级别,我大意了,没有闪,这就导致跟其Join的表的SQL变得很慢,对的应用接口的
2022-05-26

浅谈:为什么Web前端开发技术如此受欢迎?

随着互联网的发展,Web前端的应用范围更加广泛,除了网页,Web前端更广泛应用于各类APP中,渗透到我们生活的方方面面。Web前端开发好吗?为什么Web前端开发技术会如此受欢迎?
2023-06-03

云服务器速度比个人电脑快吗为什么这么慢

另外,云服务器的使用也可以使得数据更加安全和可靠。因为云服务器可以提供高可用性和高安全性的服务,当用户的数据出现问题时,云服务器可以快速地为用户提供数据备份和恢复的服务,保证用户数据的安全性。此外,云服务器的高可扩展性也可以为用户提供更多的资源和更高的灵活性,从而满足用户的各种应用需求,使得用户可以更加高效地利用云服务器的资源,提高应用效率。
2023-10-27

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录