首页 > 数据库 >mysql 临时表

mysql 临时表

时间:2023-02-14 10:06:27浏览次数:40  
标签:内部 临时 MySQL mysql 查询 使用 排序

1.情景展示

在实际开发过程中,当现有手段无法满足我们想要的数据时,我们就可以通过创建临时表,保存一些临时数据的方式,来用作数据的过渡。

2.具体分析

临时表只在当前连接可见,当关闭连接时,MySQL会自动删除表并释放所有空间;

使用其他MySQL客户端程序连接MySQL数据库服务器来创建临时表,那么只有在关闭客户端程序时才会销毁临时表(当然也可以手动删除)。

在mysql中,临时表可分为:外表临时表和内部临时表

3.外部临时表(推荐使用)

通过CREATE TEMPORARY TABLE 创建的临时表,这种临时表称为外部临时表。

这种临时表的命名与非临时表可以同名(同名后非临时表将对当前会话不可见,直到临时表被删除)。

引擎类型:memory(heap)、myisam、merge、innodb ,不支持mysql cluster(簇);

注意:

自己所用的数据库账号要有建立临时表的权限;

在同一条sql中,不能关联2次相同的临时表;

临时表在建立连接时可见(准确地来说是可用),关闭时会清除空间,删除临时表(也可以通过DROP TABLE手动删表);

show tables 不会列出临时表(对外不可见);

不能使用rename重命名临时表。但是,你可以alter table代替:只能使用alter table old_tp_table_name rename new_tp_table_name;

影响使用replication功能。

简单来说,就是:临时表的用法和普通表一样。

举例:

通常情况下,我喜欢在存储过程当中,使用临时表。

mysql 临时表_数据

4.内部临时表(尽量规避)

内部临时表是一种特殊轻量级的临时表,用来进行性能优化。

这种临时表会被MySQL自动创建并用来存储某些操作的中间结果,这些操作可能包括在优化阶段或者执行阶段。

这种内部表对用户来说是不可见的,但是通过EXPLAIN或者SHOW STATUS可以查看MYSQL是否使用了内部临时表用来帮助完成某个操作。

内部临时表在SQL语句的优化过程中扮演着非常重要的角色, MySQL中的很多操作都要依赖于内部临时表来进行优化。

但是使用内部临时表需要创建表以及中间数据的存取代价,所以用户在写SQL语句的时候应该尽量的去避免使用临时表。

(如果用户在书写SQL语句的时候能够尽量少的使用内部临时表进行查询优化,将有效的提高查询执行的效率。)

内部临时表有两种类型:

一种是HEAP临时表,这种临时表的所有数据都会存在内存中,对于这种表的操作不需要IO操作;

另一种是OnDisk临时表,顾名思义,这种临时表会将数据存储在磁盘上。

OnDisk临时表用来处理中间结果比较大的操作:如果HEAP临时表存储的数据大于MAX_HEAP_TABLE_SIZE(详情请参考MySQL手册中系统变量部分),HEAP临时表将会被自动转换成OnDisk临时表。

OnDisk临时表在5.7中可以通过INTERNAL_TMP_DISK_STORAGE_ENGINE系统变量选择使用MyISAM引擎或者InnoDB引擎。

如何知道SQL查询语句到底有没有使用内部临时表?

需要通过expalin来完成,具体表现形式有两种:见文末推荐。

mysql会使用内部临时表的情况汇总:

情形1:在SQL语句中使用SQL_BUFFER_RESULT

SQL_BUFFER_RESULT主要用来让MySQL尽早的释放表上的锁。

因为如果数据量很大的话,需要较长时间将数据发送到客户端,通过将数据缓冲到临时表中可以有效的减少读锁对表的占用时间。

mysql 临时表_数据_02

情形2:使用派生表(DERIVED_TABLE)

mysql 临时表_mysql_03

类似这种,但是,这个没有用内部临时表,等有合适案例了,再补上。

可通过SELECT @@optimizer_switch;语句来查看derived_merge当前的状态(on/off);

可使用:set optimizer_switch='derived_merge=off'来禁止derived table合并到外层的Query中。

mysql 5.1中开始引入optimizer_switch, 控制mysql优化器行为。他有一些结果集,通过on和off控制开启和关闭优化器行为。使用有效期全局和会话两个级别;

在mysql优化语句过程中,可通过设置optimizer_switch控制优化行为。

情形3:查询系统表

如果我们查询系统表的话,系统表的数据将被存储到内部临时表中。

当我们使用EXPLAIN来查看是否读取系统表数据需要利用到内部临时表时,得到的结果为:否;

mysql 临时表_SQL_04

但是,这并不意味着查询系统表没有用到内部临时表;

mysql 临时表_mysql_05

查询系统表前,临时表数量为10;查询后,临时表数量为18。

mysql 临时表_mysql_06

情形4:使用distinct或者group by且字段没有设置索引

town_village_mapping表没有任何索引

mysql 临时表_MySQL_07

我们可以看到,无论是:group by 还是distinct,都是用了内部临时表;

mysql 临时表_数据_08

town_village_mapping_old表的county_code字段有普通索引

mysql 临时表_MySQL_09

我们可以看到:此时走的就是索引,并且没有使用内部临时表。

mysql 临时表_SQL_10

说明:这里,没有考虑索引失效的情况,具体问题具体分析。

情形5:关联查询+order by

MySQL如何执行关联查询?

MySQL对任何关联都执行嵌套循环(Block Nested Loop)关联操作,即MySQL先在一个表中循环取出单条数据,然后再嵌套循环到一个表中寻找匹配的行,依次下去直到找到的有匹配的行为止。然后根据各个表匹配的行,返回查询中需要的各个列。

我们可以看到:两表关联,在没有排序的情况下,是不会使用内部临时表的;

mysql 临时表_数据_11

但是,当我们加上排序字段后,将会使用内部临时表。

mysql 临时表_SQL_12

在关联查询的时候如果需要排序(有ORDER BY子句),MySQL都会将关联的结果存放在一个临时表中,然后在所有的关联都结束后,再进行文件排序。

这种情况下Extra字段可以看到Using temporary;Using filesort;

如果查询中有LIMIT的话,LIMIT也会在排序之后应用,所以即使需要返回较少的数据,临时表和需要排序的数据量仍然会非常大。

MySQL的执行计划是一棵左侧深度优先的树。

mysql 临时表_MySQL_13

不过,如果有超过n个表的关联,那么需要检查n的阶乘种关联顺序。我们称之为所有可能的执行计划的“搜索空间”。实际上,当需要关联的表超过optimizer_search_depth的限制的时候,就会选择“贪婪”搜索模式。

无论如何排序都是一个成本很高的操作,所以从性能角度考虑,应尽可能避免排序或者尽可能避免对大量数据进行排序。如果需要排序的数据量小于排序缓冲区,MySQL使用内存进行“快速排序”操作。如果内存不够排序,那么MySQL会先将数据分块,对每个独立的块使用“快速排序”进行排序,并将各个块的排序结果存放在磁盘上,然后将各个排序的块进行合并,最后返回排序结果。

情形6:表连接+group by

没加group by之前

mysql 临时表_SQL_14

加group by之后

mysql 临时表_SQL_15

情形6:group by 与 order by 不同列

mysql 临时表_SQL_16

mysql 临时表_SQL_17

我们可以看到,当group by与order by使用相同列时,不会使用内部临时表;

但是,当group by与order by使用的列名不同时,就会触发内部临时表。

mysql 临时表_SQL_18

情形7:distinct 与 order by 不同列

由情形4,我们知道:

当distinct后面的列使用索引的话,将不会使用内部临时表;

mysql 临时表_MySQL_19

mysql 临时表_MySQL_20

我们可以再次看到,当distinct走索引,且排序字段与distinct相同时,mysql是不会用内部临时表的;

但是,当order by后面的字段与distinct 字段不相同时,将会使用内部临时表。

mysql 临时表_MySQL_21

情形8:使用union去重

先看union all(不去重)

mysql 临时表_数据_22

不去重的情况下,不会使用内部临时表;

但是,如果去重的话,将会使用内部临时表。

mysql 临时表_SQL_23

 

.....(未完待续)

写在最后

  哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!



作者:Marydon

标签:内部,临时,MySQL,mysql,查询,使用,排序
From: https://blog.51cto.com/u_15964717/6055548

相关文章

  • mysql 日期类型计算
    1.情景展示在进行按日期统计数据的时候,我们经常需要对日期的开始时间和结束时间有要求;在mysql中,日期字段如何进行时间的计算呢?2.to_days()to_days(日期)函数:返回从0000年(公......
  • mysql 快速备份表数据
    1.情景展示在工作过程中,我们往往会有对表数据进行备份的需求,比如说:对表数据进行大量操作时,为了以防万一,最好是将数据进行备份,以免操作不当,导致无法恢复原有的数据。2.解决方......
  • mysql 报错:Every derived table must have its own alias
    1.情景展示使用mysql对派生表查询数据的时候,报错信息如下:Everyderivedtablemusthaveitsownalias使用谷歌翻译成中文:每个派生表都必须有自己的别名。2.具体分析因为习......
  • mysql 获取系统当前时间的3种方式
    1.获取系统当前日期+时间方式一:now()方式二:sysdate()以上两种方式,对应日期类型:datetime。方式三:CURRENT_TIMESTAMP()/CURRENT_TIMESTAMP对应日期类型:timestamp。方式四:to_da......
  • mysql、oracle like查询不走索引的解决方案
    1.情景展示我们知道:无论是mysql还是oracle,只要使用like查询,就可能会面临索引失效(不走索引)的问题;下面,我们将一起来看看什么情况下,索引会失效,以及如何解决不走索引的问题。已......
  • mysql 非空判断(判断字段值是否为空)
    1.情景展示mysql如何判断表字段值是否为空?2.非空判断方式一:表字段+isnotnull方式二:notisnull(表字段)方式三:!isnull(表字段)3.为空判断方式一:表字段+isnull方式二:is......
  • mysql 循环批量建表(表结构相同,表名可以自定义)
    1.情景展示现在有这样一种需求:我需要建两百多张表,这些表的表结构相同,表的名称也是提前拟定好的,必须使用指定的表名;如果使用一个个写SQL语句,那不还得累死,所以,我想到了可不可......
  • mysql limit分页用法讲解
    1.情景展示在Oracle当中,使用rownum来进行分页;而在mysql中,是没有rownum的,需要通过limit来实现。2.用法介绍limit[offset,]rowslimit后面可以跟一个参数,也可以跟两个参数;格式......
  • mysql、oracle 分组查询,每组取一条数据
    1.情景展示有这样一种需求:将数据按照机构进行分组,然后取每个机构下只取一条记录,如何实现?2.mysql分组查询出来某字段,然后和原来的表进行关联查询。方式一:通过内连接来实现查......
  • MySQL 8.0 修改root远程登录【ERROR 1410 (42000): You are not allowed to create a
    MySQL8.0的数据库root用户默认无法远程登录,需要修改root的远程授权,如下:mysql>grantallprivilegeson*.*to'root'@'%';ERROR1410(42000):Youarenotallowed......