MySQL 临时表的原理以及优化方法

 更新时间:2022年08月22日 10:26:40   作者:刘Java  
这篇文章主要介绍了MySQL 临时表的原理以及优化方法,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下

1 临时表

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

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

2 union临时表优化

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

union语句的执行流程为:

  • 创建一个内存临时表。
  • 执行第一个子查询,得到值,并存入临时表中。
  • 执行第二个子查询:依次拿每一行数据和临时表中的每一行数据比较,如果重复则不会插入,这样就实现了去重的功能
  • 从临时表中按行取出数据,返回结果,并删除临时表。在最后这一步还可以对临时表进行其他操作,比如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;  

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

  • 创建内存临时表,表里有两个字段m和c,主键是m;
  • 扫描表t1的索引a,依次取出叶子节点上的id值,计算id%10的结果,记为x;
    • 如果临时表中没有主键为x的行,就插入一个记录(x,1);
    • 如果表中有主键为x的行,就将x这一行的c值加1;
    • 遍历完成后,再根据字段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字段是有序的,那么在处理时(比如计算每组数量、个数等等),因为跟着的字段有索引,那么相同的值肯定是在一起的、连续的,所以直接顺序扫描输入的数据即可,不需要临时表,也不需要再额外排序。

总结:

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

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

另外,对于distinct查询来说,如果无法使用索引,则也会使用到临时表,也会进行分组,它和group by的区别是不需要排序。

到此这篇关于MySQL 临时表的原理以及优化方法的文章就介绍到这了,更多相关MySQL 临时表 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Mysql 5.7.20压缩版下载和安装简易教程

    Mysql 5.7.20压缩版下载和安装简易教程

    这篇文章主要介绍了Mysql 5.7.20压缩版下载和安装简易教程,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2017-11-11
  • MYSQL之on和where的区别解读

    MYSQL之on和where的区别解读

    这篇文章主要介绍了MYSQL之on和where的区别解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • mysql插入中文数据变成问号的解决方案

    mysql插入中文数据变成问号的解决方案

    这篇文章主要介绍了mysql插入中文数据变成问号的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • 教你巧用mysql位运算解决多选值存储的问题

    教你巧用mysql位运算解决多选值存储的问题

    如果你不知道什么是位运算的话,那么请你先去看看基础的C语言教程吧,下面这篇文章主要给大家介绍了关于如何巧用mysql位运算解决多选值存储问题的相关资料,需要的朋友可以参考下
    2022-02-02
  • mysql 8.0.16 压缩包安装配置方法图文教程

    mysql 8.0.16 压缩包安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 8.0.16 压缩包安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • 如何解决mysql表输入中文出现问号的问题

    如何解决mysql表输入中文出现问号的问题

    这篇文章主要介绍了如何解决mysql表输入中文出现问号的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • mysql中find_in_set()函数用法及自定义增强函数详解

    mysql中find_in_set()函数用法及自定义增强函数详解

    这篇文章主要给大家介绍了关于mysql中find_in_set()函数用法及自定义增强函数的相关资料,在MySQL 数据库中进行复杂的查询语句,例如对多个字段进行筛选和排序,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • Ubuntu中更改MySQL数据库文件目录的方法

    Ubuntu中更改MySQL数据库文件目录的方法

    这篇文章主要给大家介绍了关于在Ubuntu中更改MySQL数据库文件目录的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-11-11
  • Mysql聚合函数的使用介绍

    Mysql聚合函数的使用介绍

    今天的章节我们将要来学习一下 “聚合函数” ;首先我们需要学习聚合函数对数据进行统计分析,比如说求最大值、最小值、平均值之类的场景。但是单纯的使用聚合函数,只能做全表范围的统计分析
    2022-10-10
  • MySQL中的联合索引学习教程

    MySQL中的联合索引学习教程

    这篇文章主要介绍了MySQL中的联合索引学习教程,其中谈到了联合索引对排序的优化等知识点,需要的朋友可以参考下
    2015-11-11

最新评论