MySQL 临时表的原理以及优化手段

3A网络
• 阅读 379

1 临时表

sort buffer、内存临时表和join buffer,这三个数据结构都是用来存放语句执行过程中的中间数据,以辅助SQL语句的执行的。其中,在排序的时候用到了sort buffer,在使用join语句的时候用到了join buffer。

而使用临时表的时候,ExplainExtra字段中具有Using temporary标记。union、group by、distinct等等查询都有可能使用到临时表。

2 union临时表优化

使用union的时候,就需要用到内存临时表来进行去重。

union语句的执行流程为:

  1. 创建一个内存临时表。
  2. 执行第一个子查询,得到值,并存入临时表中。
  3. 执行第二个子查询:依次拿每一行数据和临时表中的每一行数据比较,如果重复则不会插入,这样就实现了去重的功能
  4. 从临时表中按行取出数据,返回结果,并删除临时表。在最后这一步还可以对临时表进行其他操作,比如limit、ORDER BY。

如果使用union all,则不需要去重,也就不需要临时表了。在执行的时候,就依次执行子查询,得到的结果直接作为结果集的一部分,发给客户端。因此,除非确实需要服务器消除重复的行,否则就一定要使用UNION ALL,这一点很重要。如果没有ALL关键字,MySQL会给临时表加上DISTINCT选项,这会导致对整个临时我的数据做唯一性检查。这样做的代价非常高。如果不需要这些检查,那么甚至都不需要临时表。

另外,避免对于union之后的结果集进行操作,也能避免临时表的使用,通常需要手工地将MHERE、LIMIT、ORDER BY等子句“下推”到UNION的各个子查询中,以便优化器可以充分利用这些条件进行优化,使得union的结果就是最终的结果(例如,直接将这些子句冗余地写一份到各个子查询)。

3 group by临时表优化

另外一个使用临时表的例子是group by,group by还具有隐藏的排序的语句,即在对某些字段进行分组之后,将数据再根据这些字段进行排序,最后返回排序后的结果。

如下sql:

  select id%10 as m, count(*) as c from t1 group by m;  

这个语句的执行流程是这样的:

  1. 创建内存临时表,表里有两个字段m和c,主键是m;
  2. 扫描表t1的索引a,依次取出叶子节点上的id值,计算id%10的结果,记为x;
    1. 如果临时表中没有主键为x的行,就插入一个记录(x,1);
    2. 如果表中有主键为x的行,就将x这一行的c值加1;
  3. 遍历完成后,再根据字段m做排序,得到结果集返回给客户端。

此时,Explain的Extra字段中具有Using temporary; Using filesort标记。

如果并不需要对结果进行排序,那可以在SQL语句末尾增加order by null,即:

  select id%10 as m, count(*) as c from t1 group by m order by null;  

这样就跳过了最后排序的阶段,直接从临时表中取数据返回。

内存临时表的大小是有限制的,参数tmp_table_size就是控制这个内存大小的,默认是16M。如果要处理的数据超过了最大大小,那么MySQL会把内存临时表转成磁盘临时表,而磁盘临时表默认使用的引擎是InnoDB,因此会按主键顺序存储数据,所以最终取出的结果还是默认有序的。

对于Group By的临时表的优化,同样是使用索引:因为如果进行Group By字段是有序的,那么在处理时(比如计算每组数量、个数等等),因为跟着的字段有索引,那么相同的值肯定是在一起的、连续的,所以直接顺序扫描输入的数据即可,不需要临时表,也不需要再额外排序。

总结:

  1. 如果语句执行过程可以一边读数据,一边直接得到结果,是不需要额外内存的,否则就需要额外的内存,来保存中间结果;
  2. join_buffer是无序数组,sort_buffer是有序数组,临时表是二维表结构;

如果执行逻辑需要用到二维表特性,就会优先考虑使用临时表。比如我们的例子中,union需要用到唯一索引约束, group by还需要用到另外一个字段来存累积计数。

另外,对于distinct查询来说,如果无法使用索引,则也会使用到临时表,也会进行分组,它和group by的区别是不需要排序。想尝试的小伙伴可以在3A云服务器上部署一套环境,自己学习一下。

点赞
收藏
评论区
推荐文章
Wesley13 Wesley13
2年前
DB2的一种临时表写法
最近在使用DB2的临时表,学到了一种不用创建临时表再删除临时表的写法:SELECT\FROMTABLE(VALUES(COLUMN\_VALUE,COLUMN\_VALUE))TABLE\_NAME(COLUMN\_NAME,COLUMN\_NUM).比如:SELECTA,BFROMTABLE(VALUES('1','2'),('
Wesley13 Wesley13
2年前
MySql 临时表
今天在项目中遇到一个,当mysql的in语句中数据量很大时,建立一个临时表的例子。于是楼主整理了一下关于临时表的知识,与大家分享一下~首先,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。因此在不同的连接中可以创建同名的临时表,并且操作属于本连接的临时表。建立临时表:CREATETEMPORARY TABLEt
Easter79 Easter79
2年前
SQL Server中的临时表
SQLServer中的临时表官方:https://technet.microsoft.com/zhcn/library/ms177399(vsql.105).aspx(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F
Stella981 Stella981
2年前
Explain(MySQL高级知识四)
前言:explain(执行计划),使用explain关键字可以模拟优化器执行sql查询语句,从而知道MySQL是如何处理sql语句。explain主要用于分析查询语句或表结构的性能瓶颈。注:本系列随笔如无特殊说明都MySQL版本都为5.7.22。1.explain的作用通过explainsql语句可以知道如下内容:①表的读取顺序。(
Wesley13 Wesley13
2年前
SQL语句优化
SQL语句优化规范:1\.使用mysqlexplain对sql执行效率进行检测,explain显示了mysql如何使用索引来处理select语句以及连接表。可以帮助选择更好的索引和写出更优化的查询语句。1)使用方法:在select语句前加上explain即可2)explain分析结果形式如下:table|type
Wesley13 Wesley13
2年前
mysql查询优化explain命令详解
mysql查询优化的方法有很多种,explain是工作当中用的比较多的一种检查方式。explain翻译即解释,就是看mysql语句的查询解释计划,从解释计划我们能很清楚的看到解释的语句有没有合理用到索引,扫描了多少行数,有没有触及全表扫描、用到临时表等影响慢查询的原因。使用很简单,如explainselect\fromuse
Wesley13 Wesley13
2年前
Mysql占用过高CPU时的优化手段
慢查询日志,将那些执行时间过长且占用资源过多的SQL拿来进行explain分析,导致CPU过高,多数是GroupBy、OrderBy排序问题所导致,然后慢慢进行优化改进。比如优化insert语句、优化groupby语句、优化orderby语句、优化join语句等等;3)考虑定时优化文件及索引;4)定期分析表,使用optimizetable;
Stella981 Stella981
2年前
SQL Server中的临时表
SQLServer中的临时表官方:https://technet.microsoft.com/zhcn/library/ms177399(vsql.105).aspx(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F
Wesley13 Wesley13
2年前
MySQL视图,函数,触发器,存储过程
1\.视图  视图是一个虚拟表,它的本质是根据SQL语句获取动态的数据集,并为其命名,用户使用时只需使用【名称】即可获取结果集,可以将该结果集当做表来使用。使用视图我们可以把查询过程中的临时表摘出来,用视图去实现,这样以后再想操作该临时表的数据时就无需重写复杂的sql了,直接去视图中查找即可,但视图有明显地效率问题,并且视
Wesley13 Wesley13
2年前
JOIN关联表中ON,WHERE后面跟条件的区别
SQL中on条件与where条件的区别      数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。     在使用leftjion时,on和where条件的区别如下:1、on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。2、where条件是