您的当前位置:首页MySQL 中的两种临时表

MySQL 中的两种临时表

2023-11-10 来源:哗拓教育

 

  • 如果SQL语句中包含了DERIVED_TABLE。

  •  

    在5.7中,由于采用了新的优化方式,我们需要使用 set optimizer_switch=’derived_merge=off’来禁止derived table合并到外层的Query中。

    例如:

     

    mysql> explain format=json select * from (select * from t1) as tt;

    EXPLAIN

    {

      "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "2.40"

    },

    "table": {

      "table_name": "tt",

      "access_type": "ALL",

      ...

      "materialized_from_subquery": {

    "using_temporary_table": true,

    ...

     

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

  •  

    我们当前不能使用EXPLAIN来查看是否读取系统表数据需要利用到内部临时表,但是可以通过SHOW STATUS来查看是否利用到了内部临时表。

    例如:

     

    mysql> select * from information_schema.character_sets;

    mysql> show status like ‘CREATE%‘;

     

  • 如果DISTINCT语句没有被优化掉,即DISTINCT语句被优化转换为GROUP BY操作或者利用UNIQUE INDEX消除DISTINCT, 内部临时表将会被使用。

  •  

    mysql> explain format=json select distinct a from t1;

    EXPLAIN

    {

    {

      "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "1.60"

    },

    "duplicates_removal": {

      "using_temporary_table": true,

    ...

     

  • 如果查询带有ORDER BY语句,并且不能被优化掉。下面几种情况会利用到内部临时表缓存中间数据,然后对中间数据进行排序。

  •  

    1)如果连接表使用BNL(Batched Nestloop)/BKA(Batched Key Access)例如:

     

    1))BNL默认是打开的

     

    mysql> explain format=json select * from t1, t1 as t2 order by t1.a;

    EXPLAIN

    {

      "query_block": {

      "select_id": 1,

      "cost_info": {

    "query_cost": "22.00"

      },

      "ordering_operation": {

    "using_temporary_table": true,

      ...

     

    2))关掉BNL后,ORDER BY将直接使用filesort。

     

    mysql> set optimizer_switch=‘block_nested_loop=off‘;

    Query OK, 0 rows affected (0.00 sec)

    mysql> explain format=json select * from t1, t1 as t2 order by t1.a;

    EXPLAIN

    {

       "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "25.00"

    },

    "ordering_operation": {

      "using_filesort": true,

    ...

     

    2)ORDER BY的列不属于执行计划中第一个连接表的列。

     

    例如:

     

    mysql> explain format=json select * from t as t1, t as t2 order by t2.a;

    EXPLAIN

    {

       "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "25.00"

    },

    "ordering_operation": {

      "using_temporary_table": true,

    ...

     

    3)如果ORDER BY的表达式是个复杂表达式。

     

    那么什么样的ORDER BY表达式,MySQL认为是复杂表达式呢?

     

    1))如果排序表达式是SP或者UDF。

     

    例如:

     

    drop function if exists func1;

    delimiter |

    create function func1(x int)

    returns int deterministic

    begin

    declare z1, z2 int;

    set z1 = x;

    set z2 = z1+2;

    return z2;

    end|

    delimiter ;

    explain format=json select * from t1 order by func1(a);

    {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "2.20"

    },

    "ordering_operation": {

      "using_temporary_table": true,

    ...

     

    2))ORDER BY的列包含聚集函数

     

    为了简化执行计划,我们利用INDEX来优化GROUP BY语句。

    例如:

     

      create index idx1 on t1(a);

      explain format=json SELECt a FROM t1 group by a order by sum(a);

      | {

       "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "1.20"

    },

    "ordering_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

      "grouping_operation": {

    "using_filesort": false,

    ...

      drop index idx1 on t1;

     

    3))ORDER BY的列中包含有SCALAR SUBQUERY,当然该SCALAR SUBQUERY没有被优化掉。

     

    例如:

     

    explain format=json select (select rand() from t1 limit 1) as a from t1 order by a;

    | {

      "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "1.20"

    },

    "ordering_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

    ...

     

    4) 如果查询既带有ORDER BY同时也有GROUP BY语句,但是两个语句使用的列不相同。

     

    注意: 如果是5.7,我们需要将sql_mode设置为非only_full_group_by模式,否则会报错。

     

    同样为了简化执行计划,我们利用INDEX来优化GROUP BY语句。

     

    例如:

     

    set sql_mode=‘‘;

    create index idx1 on t1(b);

    explain format=json select t1.a from t1 group by t1.b order by 1;

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "1.40"

    },

    "ordering_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

      "grouping_operation": {

    "using_filesort": false,

    ...

    drop index idx1 on t1;

     

  • 如果查询带有GROUP BY语句,并且不能被优化掉。下面几种情况会利用到内部临时表缓存中间数据,然后对中间数据进行GROUP BY。

  •  

    1)如果连接表使用BNL(Batched Nestloop)/BKA(Batched Key Access)。例如:

     

    explain format=json select t2.a from t1, t1 as t2 group by t1.a;

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "8.20"

    },

    "grouping_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

      "cost_info": {

    "sort_cost": "4.00"

    ...

     

    2) 如果GROUP BY的列不属于执行计划中的第一个连接表。

     

    例如:

     

    explain format=json select t2.a from t1, t1 as t2 group by t2.a;

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "8.20"

    },

    "grouping_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

      "nested_loop": [

    ...

     

    3) 如果GROUP BY语句使用的列与ORDER BY语句使用的列不同。

     

    例如:

     

    set sql_mode=‘‘;

    explain format=json select t1.a from t1 group by t1.b order by t1.a;

    | {

       "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "1.40"

    },

    "ordering_operation": {

      "using_filesort": true,

      "grouping_operation": {

    "using_temporary_table": true,

    "using_filesort": false,

    ...

     

    4) 如果GROUP BY带有ROLLUP并且是基于多表外连接。

     

    例如:

     

    explain format=json select sum(t1.a) from t1 left join t1 as t2 on true group by t1.a with rollup;

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "7.20"

    },

    "grouping_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

      "cost_info": {

    "sort_cost": "4.00"

      },

    ...

     

    5) 如果GROUP BY语句使用的列来自于SCALAR SUBQUERY,并且没有被优化掉。

     

    例如:

     

    explain format=json select (select avg(a) from t1) as a from t1 group by a;

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "3.40"

    },

    "grouping_operation": {

      "using_temporary_table": true,

      "using_filesort": true,

      "cost_info": {

    "sort_cost": "2.00"

      },

    ...

     

  • IN表达式转换为semi-join进行优化

  •  

    1) 如果semi-join执行方式为Materialization

    例如:

     

    set optimizer_switch=‘firstmatch=off,duplicateweedout=off‘;

    explain format=json select * from t1 where a in (select b from t1);

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "5.60"

    },

    "nested_loop": [

      {

    "rows_examined_per_scan": 1,

      "materialized_from_subquery": {

    "using_temporary_table": true,

    "query_block": {

      "table": {

    "table_name": "t1",

    "access_type": "ALL",

     

    ...

     

    2) 如果semi-join执行方式为Duplicate Weedout

     

    例如:

     

    set optimizer_switch=‘firstmatch=off‘;

    explain format=json select * from t1 where a in (select b from t1);

    | {

    "query_block": {

    "select_id": 1,

    "cost_info": {

      "query_cost": "4.80"

    },

    "duplicates_removal": {

      "using_temporary_table": true,

      "nested_loop": [

    {

    ...

     

  • 如果查询语句带有UNION,MySQL将利用内部临时表帮助UNION操作消除重复。

  •  

    例如:

     

    explain format=json select * from t1 union select * from t1;

    | {

    "query_block": {

    "union_result": {

      "using_temporary_table": true,

      "table_name": "",

    ...

     

  • 如果查询语句使用多表更新。

  •  

    这里Explain不能看到内部临时表被利用,所以需要查看status。

    例如:

     

    update t1, t1 as t2 set t1.a=3;

    show status like ‘CREATE%‘;

     

  • 如果聚集函数中包含如下函数,内部临时表也会被利用。

  •  

    1) count(distinct *)

    例如:

    explain format=json select count(distinct a) from t1;

    2) group_concat

    例如:

    explain format=json select group_concat(b) from t1;

     

    总之,上面列出了10种情况,MySQL将利用内部临时表进行中间结果缓存,如果数据量比较大的话,内部临时表将会把数据存储在磁盘上,这样显然会对性能有所影响。为了尽可能的减少性能损失,我们需要尽量避免上述情况的出现。

    MySQL 中的两种临时表

    标签:

    小编还为您整理了以下内容,可能对您也有帮助:

    mysql之临时表

    临时表:一种特殊的表,用来存储查询的中间结果,并且会随着当前连接的结束而自动删除。mysql中有2种临时表,分别是内部临时表和外部临时表。

    外部临时表关键字:TEMPORARY 。

    外部临时表特征:

    1、关键字TEMPORARY

    2、临时表创建完成之后,只有当前可见,其他连接是看不到的,具有连接隔离性

    3、临时表在当前连接结束之后,会自动删除。

    临时表可以存储在内存和磁盘。

    Mysql中的临时表使用方法讲解

    当工作在非常大的表上时,你可能偶尔需要运行很多查询获得一个大量数据的小的子集,不是对整个表运行这些查询,而是让MySQL每次找出所需的少数记录,将记录选择到一个临时表可能更快些,然后多这些表运行查询。

    创建临时表很容易,给正常的CREATE TABLE语句加上TEMPORARY关键字:

    CREATE TEMPORARY TABLE tmp_table (name VARCHAR(10) NOT NULL,

    value INTEGER NOT NULL)

    临时表将在你连接MySQL期间存在。当你断开时,MySQL将自动删除表并释放所用的空间。当然你可以在仍然连接的时候删除表并释放空间。

    DROP TABLE tmp_table

    如果在你创建名为tmp_table临时表时名为tmp_table的表在数据库中已经存在,临时表将有必要屏蔽(隐藏)非临时表tmp_table。

    如果你声明临时表是一个HEAP表,MySQL也允许你指定在内存中创建它:

    CREATE TEMPORARY TABLE tmp_table (name VARCHAR(10) NOT NULL,

    value INTEGER NOT NULL) TYPE = HEAP

    因为HEAP表存储在内存中,你对它运行的查询可能比磁盘上的临时表快些。然而,HEAP表与一般的表有些不同,且有自身的。详见MySQL参考手册。

    正如前面的建议,你应该测试临时表看看它们是否真的比对大量数据库运行查询快。如果数据很好地索引,临时表可能一点不快。

    MySQL问答系列之什么情况下会用到临时表



    临时表介绍

    什么是临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。为什么会产生临时表:一般是由于复杂的SQL导致临时表被大量创建

    临时表分为两种,一种是内存临时表,一种是磁盘临时表。内存临时表采用的是memory存储引擎,磁盘临时表采用的是myisam存储引擎(磁盘临时表也可以使用innodb存储引擎,通过internal_tmp_disk_storage_engine参数来控制使用哪种存储引擎,从mysql5.7.6之后默认为innodb存储引擎,之前版本默认为myisam存储引擎)。分别通过Created_tmp_disk_tables 和 Created_tmp_tables 两个参数来查看产生了多少磁盘临时表和所有产生的临时表(内存和磁盘)。

    MySQL在以下几种情况会创建临时表:

    1、UNION查询;


    2、用到TEMPTABLE算法或者是UNION查询中的视图;


    3、ORDER BY和GROUP BY的子句不一样时;


    4、表连接中,ORDER BY的列不是驱动表中的;


    5、DISTINCT查询并且加上ORDER BY时;


    6、SQL中用到SQL_SMALL_RESULT选项时;


    7、FROM中的子查询;


    8、子查询或者semi-join时创建的表;

    EXPLAIN 查看执行计划结果的 Extra 列中,如果包含 Using Temporary 就表示会用到临时表。

    当然了,如果临时表中需要存储的数据量超过了上限( tmp-table-size 或 max-heap-table-size 中取其大者),这时候就需要生成基于磁盘的临时表了。

    在以下几种情况下,会创建磁盘临时表:

    1、数据表中包含BLOB/TEXT列;


    2、在 GROUP BY 或者 DSTINCT 的列中有超过 512字符 的字符类型列(或者超过 512字节的 二进制类型列,在5.6.15之前只管是否超过512字节);


    3、在SELECT、UNION、UNION ALL查询中,存在最大长度超过512的列(对于字符串类型是512个字符,对于二进制类型则是512字节);


    4、执行SHOW COLUMNS/FIELDS、DESCRIBE等SQL命令,因为它们的执行结果用到了BLOB列类型。

    从5.7.5开始,新增一个系统选项 internal_tmp_disk_storage_engine 可定义磁盘临时表的引擎类型为 InnoDB,而在这以前,只能使用 MyISAM。而在5.6.3以后新增的系统选项 default_tmp_storage_engine 是控制 CREATE TEMPORARY TABLE 创建的临时表的引擎类型,在以前默认是MEMORY,不要把这二者混淆了。

    详见下例

    mysql> set default_tmp_storage_engine = "InnoDB";
    -rw-rw---- 1 mysql mysql 8558 Jul 7 15:22 #sql4b0e_10_0.frm -- InnoDB引擎的临时表
    -rw-rw---- 1 mysql mysql 98304 Jul 7 15:22 #sql4b0e_10_0.ibd
    -rw-rw---- 1 mysql mysql 8558 Jul 7 15:25 #sql4b0e_10_2.frm
    mysql> set default_tmp_storage_engine = "MyISAM";
    -rw-rw---- 1 mysql mysql 0 Jul 7 15:25 #sql4b0e_10_2.MYD -- MyISAM引擎的临时表
    -rw-rw---- 1 mysql mysql 1024 Jul 7 15:25 #sql4b0e_10_2.MYI
    mysql> set default_tmp_storage_engine = "MEMORY";
    -rw-rw---- 1 mysql mysql 8558 Jul 7 15:26 #sql4b0e_10_3.frm -- MEMORY引擎的临时表
    总结

    MySQL问答系列之什么情况下会用到临时表



    临时表介绍

    什么是临时表:MySQL用于存储一些中间结果集的表,临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。为什么会产生临时表:一般是由于复杂的SQL导致临时表被大量创建

    临时表分为两种,一种是内存临时表,一种是磁盘临时表。内存临时表采用的是memory存储引擎,磁盘临时表采用的是myisam存储引擎(磁盘临时表也可以使用innodb存储引擎,通过internal_tmp_disk_storage_engine参数来控制使用哪种存储引擎,从mysql5.7.6之后默认为innodb存储引擎,之前版本默认为myisam存储引擎)。分别通过Created_tmp_disk_tables 和 Created_tmp_tables 两个参数来查看产生了多少磁盘临时表和所有产生的临时表(内存和磁盘)。

    MySQL在以下几种情况会创建临时表:

    1、UNION查询;


    2、用到TEMPTABLE算法或者是UNION查询中的视图;


    3、ORDER BY和GROUP BY的子句不一样时;


    4、表连接中,ORDER BY的列不是驱动表中的;


    5、DISTINCT查询并且加上ORDER BY时;


    6、SQL中用到SQL_SMALL_RESULT选项时;


    7、FROM中的子查询;


    8、子查询或者semi-join时创建的表;

    EXPLAIN 查看执行计划结果的 Extra 列中,如果包含 Using Temporary 就表示会用到临时表。

    当然了,如果临时表中需要存储的数据量超过了上限( tmp-table-size 或 max-heap-table-size 中取其大者),这时候就需要生成基于磁盘的临时表了。

    在以下几种情况下,会创建磁盘临时表:

    1、数据表中包含BLOB/TEXT列;


    2、在 GROUP BY 或者 DSTINCT 的列中有超过 512字符 的字符类型列(或者超过 512字节的 二进制类型列,在5.6.15之前只管是否超过512字节);


    3、在SELECT、UNION、UNION ALL查询中,存在最大长度超过512的列(对于字符串类型是512个字符,对于二进制类型则是512字节);


    4、执行SHOW COLUMNS/FIELDS、DESCRIBE等SQL命令,因为它们的执行结果用到了BLOB列类型。

    从5.7.5开始,新增一个系统选项 internal_tmp_disk_storage_engine 可定义磁盘临时表的引擎类型为 InnoDB,而在这以前,只能使用 MyISAM。而在5.6.3以后新增的系统选项 default_tmp_storage_engine 是控制 CREATE TEMPORARY TABLE 创建的临时表的引擎类型,在以前默认是MEMORY,不要把这二者混淆了。

    详见下例

    mysql> set default_tmp_storage_engine = "InnoDB";
    -rw-rw---- 1 mysql mysql 8558 Jul 7 15:22 #sql4b0e_10_0.frm -- InnoDB引擎的临时表
    -rw-rw---- 1 mysql mysql 98304 Jul 7 15:22 #sql4b0e_10_0.ibd
    -rw-rw---- 1 mysql mysql 8558 Jul 7 15:25 #sql4b0e_10_2.frm
    mysql> set default_tmp_storage_engine = "MyISAM";
    -rw-rw---- 1 mysql mysql 0 Jul 7 15:25 #sql4b0e_10_2.MYD -- MyISAM引擎的临时表
    -rw-rw---- 1 mysql mysql 1024 Jul 7 15:25 #sql4b0e_10_2.MYI
    mysql> set default_tmp_storage_engine = "MEMORY";
    -rw-rw---- 1 mysql mysql 8558 Jul 7 15:26 #sql4b0e_10_3.frm -- MEMORY引擎的临时表
    总结

    技术分享 | 浅谈 MySQL 的临时表和临时文件

    本文内容来源于对客户的三个问题的思考:

    以下测试都是在 MySQL 8.0.21 版本中完成,不同版本可能存在差异,可自行测试;

    临时表和临时文件都是用于临时存放数据集的地方;

    一般情况下,需要临时存放在临时表或临时文件中的数据集应该符合以下特点:

    从临时表|临时文件产生的主观性来看,分为2类:

    用户创建临时表:

      -- 用户创建临时表(只有创建临时表的会话才能查看其创建的临时表的内容)

      注意:

      可以创建和普通表同名临时表,其他会话可以看到普通表(因为看不到其他会话创建的临时表);

      创建临时表的会话会优先看到临时表;

      -- 同名表的创建的语句如下

      当存在同名的临时表时,会话都是优先处理临时表(而不是普通表),包括:select、update、delete、drop、alter 等操作;

    查看用户创建的临时表:

      任何 session 都可以执行下面的语句;

      查看用户创建的当前 active 的临时表(不提供 optimizer 使用的内部 InnoDB 临时表信息)

      注意

      用户创建的临时表,表名为t1,

      但是通过 INNODB_TEMP_TABLE_INFO 查看到的临时表的 NAME 是#sql开头的名字,例如:#sql45aa_7c69_2 ;

      另外 information_schema.tables 表中是不会记录临时表的信息的。

    用户创建的临时表的回收:

    用户创建的临时表的其他信息&参数:

      会话临时表空间存储 用户创建的临时表和优化器 optimizer 创建的内部临时表(当磁盘内部临时表的存储引擎为 InnoDB 时);

      innodb_temp_tablespaces_dir 变量定义了创建 会话临时表空间的位置,默认是数据目录下的#innodb_temp 目录;

      文件类似temp_[1-20].ibt ;

      查看会话临时表空间的元数据:

      用户创建的临时表删除后,其占用的空间会被释放(temp_[1-20].ibt文件会变小)。

      在 MySQL 8.0.16 之前,internal_tmp_disk_storage_engine 变量定义了用户创建的临时表和 optimizer 创建的内部临时表的引擎,可选 INNODB 和 MYISAM ;

      从 MySQL 8.0.16 开始,internal_tmp_disk_storage_engine参数被移除,默认使用InnoDB存储引擎;

      innodb_temp_data_file_path 定义了用户创建的临时表使用的回滚段的存储文件的相对路径、名字、大小和属性,该文件是全局临时表空间(ibtmp1);

      可以使用语句查询全局临时表空间的数据文件大小:

    SQL 什么时候产生临时表|临时文件呢?

      需要用到临时表或临时文件的时候,optimizer 自然会创建使用(感觉是废话,但是又觉得有道理=.=!);

      (想象能力强的,可以牢记上面这句话;想象能力弱的,只能死记下面的 SQL 了。我也弱,此处有个疲惫的微笑😊)

    下面列举一些 server 在处理 SQL 时,可能会创建内部临时表的 SQL :

      SQL 包含 union | union distinct 关键字

      SQL 中存在派生表

      SQL 中包含 with 关键字

      SQL 中的order by 和 group by 的字段不同

      SQL 为多表 update

      SQL 中包含 distinct 和 order by 两个关键字

    我们可以通过下面两种方式判断 SQL 语句是否使用了临时表空间:

      # 如果 explain 的 Extra 列包含 Using temporary ,那么说明会使用临时空间,如果包含 Using filesort ,那么说明会使用文件排序(临时文件);

      如果执行 SQL 后,表的 ID 列变为了show processlist 中的 id 列的值,那么说明 SQL 语句使用了临时表空间

    SQL创建的内部临时表的存储信息:

      SQL 创建内部临时表时,优先选择在内存中,默认使用 TempTable 存储引擎(由参数 internal_tmp_mem_storage_engine 确定),

      当 temptable 使用的内存量超过 temptable_max_ram 定义的大小时,

      由 temptable_use_mmap 确定是使用内存映射文件的方式还是 InnoDB 磁盘内部临时表的方式存储数据

      (temptable_use_mmap 参数在 MySQL 8.0.16 引入,MySQL 8.0.26 版本不推荐,后续应该会移除);

      temptable_use_mmap 的功能将由MySQL 8.0.23 版本引入的 temptable_max_mmap 代替,

      当 temptable_max_mmap=0 时,说明不使用内存映射文件,等价于 temptable_use_mmap=OFF ;

      当 temptable_max_mmap=N 时,N为正整数,包含了 temptable_use_mmap=ON 以及声明了允许为内存映射文件分配的最大内存量。

      该参数的定决了这些文件使用过多空间的风险。

      内存映射文件产生的临时文件会存放于 tmpdir 定义的目录中,在 TempTable 存储引擎关闭或 mysqld 进程关闭时,回收空间;

      当 SQL 创建的内部临时表,选择 MEMORY 存储引擎时,如果内存中的临时表变的太大,MySQL 将自动将其转为磁盘临时表;

      其能使用的内存上限为 min(tmp_table_size,max_heap_table_size);

    监控 TempTable 从内存和磁盘上分配的空间:

      具体的字段含义见:Section 27.12.20.10, “Memory Summary Tables”.

    监控内部临时表的创建:

      当在内存或磁盘上创建内部临时表,服务器会增加 Created_tmp_tables 的值;

      当在磁盘上创建内部临时表时,服务器会增加 Created_tmp_disk_tables 的值,

      如果在磁盘上创建了太多的内部临时表,请考虑增加 tmp_table_size 和 max_heap_table_size 的值;

      created_tmp_disk_tables 不计算在内存映射文件中创建的磁盘临时表;

    例外项:

      临时表/临时文件一般较小,但是也存在需要大量空间的临时表/临时文件的需求:

    因为这些例外项一般需要较大的空间,所以需要考虑是否要将其存放在的挂载点上。

    其他:

      列出由失败的 alter table 创建的隐藏临时表,这些临时表以#sql开头,可以使用 drop table 删除;

      通过 lsof +L1 可以查看标识为 delete ,但还未释放空间的文件。

       如果想释放这些 delete 状态的文件,可以尝试下面的方法(不推荐,后果自负):

    普通的磁盘临时表|临时文件(一般需要较小的空间):

      临时表|临时文件的一般所需的空间较小,会优先存放于内存中,若超过一定的大小,则会转换为磁盘临时表|临时文件;

      磁盘临时表默认为 InnoDB 引擎,其存放在临时表空间中,由 innodb_temp_tablespaces_dir 定义表空间的存放目录,表空间文件类似:temp_[1-20].ibt ;MySQL 未定义 InnoDB 临时表空间的最大使用上限;

      当临时表|临时文件使用完毕后,会自动回收临时表空间文件的大小;

      innodb_temp_data_file_path 定义了用户创建的临时表使用的回滚段的存储文件的相对路径、名字、大小和属性,该文件是全局临时表空间(ibtmp1),该文件可以设置文件最大使用大小;

    例外项(一般需要较大的空间):

      load data local 语句,客户端读取文件并将其内容发送到服务器,服务器将其存储在 tmpdir 参数指定的路径中;

      在 replica 中,回放 load data 语句时,需要将从 relay log 中解析出来的数据存储在 slave_load_tmpdir(replica_load_tmpdir) 指定的目录中,该参数默认和 tmpdir 参数指定的路径相同;

      需要 rebuild table 的在线 alter table 需要使用 innodb_tmpdir 存放排序磁盘排序文件,如果 innodb_tmpdir 未指定,则使用 tmpdir 的值;

    若用户判断产生的临时表|临时文件一定会转换为磁盘临时表|临时文件,那么可以设置 set session big_tables=1;让产生的临时表|临时文件直接存放在磁盘上;

      对于需要较小空间的临时表|临时文件,MySQL 要么将其存储于内存,要么放在统一的磁盘临时表空间中,用完即释放;

      对于需要较大空间的临时表|临时文件,可以通过设置参数,将其存储于单独的目录|挂载点;例如:load local data 语句或需要重建表的在线 alter table 语句,都有对应的参数设置其存放临时表|临时文件的路径;

      当前只有 innodb_temp_data_file_path 参数可以 用户创建的临时表使用的回滚段的存储文件的大小,无其他参数可以临时表|临时文件可使用的磁盘空间;

    在mysql里怎么用临时表

    MySQL 需要创建隐式临时表来解决某些类型的查询。往往查询的排序阶段需要依赖临时表。例如,当您使用 GROUP BY,ORDER BY 或DISTINCT 时。这样的查询分两个阶段执行:首先是收集数据并将它们放入临时表中,然后是在临时表上执行排序。
    对于某些 UNION 语句,不能合并的 VIEW,子查询时用到派生表,多表 UPDATE 以及其他一些情况,还需要使用临时表。如果临时表很小,可以到内存中创建,否则它将在磁盘上创建。MySQL 在内存中创建了一个表,如果它变得太大,就会被转换为磁盘上存储。内存临时表的最大值由 tmp_table_size 或 max_heap_table_size 值定义,以较小者为准。MySQL 5.7 中的默认大小为 16MB。如果运行查询的数据量较大,或者尚未查询优化,则可以增加该值。设置阈值时,请考虑可用的 RAM 大小以及峰值期间的并发连接数。你无法无限期地增加变量,因为在某些时候你需要让 MySQL 使用磁盘上的临时表。
    注意:如果涉及的表具有 TEXT 或 BLOB 列,则即使大小小于配置的阈值,也会在磁盘上创建临时表。

    在mysql里怎么用临时表

    MySQL 需要创建隐式临时表来解决某些类型的查询。往往查询的排序阶段需要依赖临时表。例如,当您使用 GROUP BY,ORDER BY 或DISTINCT 时。这样的查询分两个阶段执行:首先是收集数据并将它们放入临时表中,然后是在临时表上执行排序。
    对于某些 UNION 语句,不能合并的 VIEW,子查询时用到派生表,多表 UPDATE 以及其他一些情况,还需要使用临时表。如果临时表很小,可以到内存中创建,否则它将在磁盘上创建。MySQL 在内存中创建了一个表,如果它变得太大,就会被转换为磁盘上存储。内存临时表的最大值由 tmp_table_size 或 max_heap_table_size 值定义,以较小者为准。MySQL 5.7 中的默认大小为 16MB。如果运行查询的数据量较大,或者尚未查询优化,则可以增加该值。设置阈值时,请考虑可用的 RAM 大小以及峰值期间的并发连接数。你无法无限期地增加变量,因为在某些时候你需要让 MySQL 使用磁盘上的临时表。
    注意:如果涉及的表具有 TEXT 或 BLOB 列,则即使大小小于配置的阈值,也会在磁盘上创建临时表。

    MySQL中关于临时表的一些基本使用方法

    临时表可能是非常有用的,在某些情况下,保持临时数据。最重要的是应该知道的临时表是,他们将当前的客户端会话终止时被删除。
    临时表中添加MySQL版本3.23。如果您使用的是旧版本的MySQL比3.23,可以不使用临时表,但可以使用堆表。
    如前所述临时表将只持续只要的会话是存在的。如果运行一个PHP脚本中的代码,该临时表将被销毁时,会自动执行完脚本后。如果已连接到MySQL数据库的服务器上,通过MySQL的客户端程序的临时表将一直存在,直到关闭客户端或手动破坏的表。
    实例
    下面是一个例子,使用临时表在PHP脚本中,使用mysql_query()函数,可以使用相同的代码。
    mysql>
    CREATE
    TEMPORARY
    TABLE
    SalesSummary
    (
    ->
    proct_name
    VARCHAR(50)
    NOT
    NULL
    ->
    ,
    total_sales
    DECIMAL(12,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    avg_unit_price
    DECIMAL(7,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    total_units_sold
    INT
    UNSIGNED
    NOT
    NULL
    DEFAULT
    0
    );
    Query
    OK,
    0
    rows
    affected
    (0.00
    sec)
    mysql>
    INSERT
    INTO
    SalesSummary
    ->
    (proct_name,
    total_sales,
    avg_unit_price,
    total_units_sold)
    ->
    VALUES
    ->
    ('cucumber',
    100.25,
    90,
    2);
    mysql>
    SELECT
    *
    FROM
    SalesSummary;
    +--------------+-------------+----------------+------------------+
    |
    proct_name
    |
    total_sales
    |
    avg_unit_price
    |
    total_units_sold
    |
    +--------------+-------------+----------------+------------------+
    |
    cucumber
    |
    100.25
    |
    90.00
    |
    2
    |
    +--------------+-------------+----------------+------------------+
    1
    row
    in
    set
    (0.00
    sec)
    当发出一个SHOW
    TABLES命令,那么临时表将不会被列在列表中。现在如果将MySQL的会话的注销,那么会发出SELECT命令,那么会发现没有在数据库中的数据。即使临时表也就不存在了。
    删除临时表:
    默认情况下,所有的临时表被删除时,MySQL的数据库连接被终止。不过要删除他们之前就应该发出DROP
    TABLE命令。
    下面的例子为删除一个临时表。
    mysql>
    CREATE
    TEMPORARY
    TABLE
    SalesSummary
    (
    ->
    proct_name
    VARCHAR(50)
    NOT
    NULL
    ->
    ,
    total_sales
    DECIMAL(12,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    avg_unit_price
    DECIMAL(7,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    total_units_sold
    INT
    UNSIGNED
    NOT
    NULL
    DEFAULT
    0
    );
    Query
    OK,
    0
    rows
    affected
    (0.00
    sec)
    mysql>
    INSERT
    INTO
    SalesSummary
    ->
    (proct_name,
    total_sales,
    avg_unit_price,
    total_units_sold)
    ->
    VALUES
    ->
    ('cucumber',
    100.25,
    90,
    2);
    mysql>
    SELECT
    *
    FROM
    SalesSummary;
    +--------------+-------------+----------------+------------------+
    |
    proct_name
    |
    total_sales
    |
    avg_unit_price
    |
    total_units_sold
    |
    +--------------+-------------+----------------+------------------+
    |
    cucumber
    |
    100.25
    |
    90.00
    |
    2
    |
    +--------------+-------------+----------------+------------------+
    1
    row
    in
    set
    (0.00
    sec)
    mysql>
    DROP
    TABLE
    SalesSummary;
    mysql>
    SELECT
    *
    FROM
    SalesSummary;
    ERROR
    1146:
    Table
    'TUTORIALS.SalesSummary'
    doesn't
    exist

    MySQL中关于临时表的一些基本使用方法

    临时表可能是非常有用的,在某些情况下,保持临时数据。最重要的是应该知道的临时表是,他们将当前的客户端会话终止时被删除。
    临时表中添加MySQL版本3.23。如果您使用的是旧版本的MySQL比3.23,可以不使用临时表,但可以使用堆表。
    如前所述临时表将只持续只要的会话是存在的。如果运行一个PHP脚本中的代码,该临时表将被销毁时,会自动执行完脚本后。如果已连接到MySQL数据库的服务器上,通过MySQL的客户端程序的临时表将一直存在,直到关闭客户端或手动破坏的表。
    实例
    下面是一个例子,使用临时表在PHP脚本中,使用mysql_query()函数,可以使用相同的代码。
    mysql>
    CREATE
    TEMPORARY
    TABLE
    SalesSummary
    (
    ->
    proct_name
    VARCHAR(50)
    NOT
    NULL
    ->
    ,
    total_sales
    DECIMAL(12,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    avg_unit_price
    DECIMAL(7,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    total_units_sold
    INT
    UNSIGNED
    NOT
    NULL
    DEFAULT
    0
    );
    Query
    OK,
    0
    rows
    affected
    (0.00
    sec)
    mysql>
    INSERT
    INTO
    SalesSummary
    ->
    (proct_name,
    total_sales,
    avg_unit_price,
    total_units_sold)
    ->
    VALUES
    ->
    ('cucumber',
    100.25,
    90,
    2);
    mysql>
    SELECT
    *
    FROM
    SalesSummary;
    +--------------+-------------+----------------+------------------+
    |
    proct_name
    |
    total_sales
    |
    avg_unit_price
    |
    total_units_sold
    |
    +--------------+-------------+----------------+------------------+
    |
    cucumber
    |
    100.25
    |
    90.00
    |
    2
    |
    +--------------+-------------+----------------+------------------+
    1
    row
    in
    set
    (0.00
    sec)
    当发出一个SHOW
    TABLES命令,那么临时表将不会被列在列表中。现在如果将MySQL的会话的注销,那么会发出SELECT命令,那么会发现没有在数据库中的数据。即使临时表也就不存在了。
    删除临时表:
    默认情况下,所有的临时表被删除时,MySQL的数据库连接被终止。不过要删除他们之前就应该发出DROP
    TABLE命令。
    下面的例子为删除一个临时表。
    mysql>
    CREATE
    TEMPORARY
    TABLE
    SalesSummary
    (
    ->
    proct_name
    VARCHAR(50)
    NOT
    NULL
    ->
    ,
    total_sales
    DECIMAL(12,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    avg_unit_price
    DECIMAL(7,2)
    NOT
    NULL
    DEFAULT
    0.00
    ->
    ,
    total_units_sold
    INT
    UNSIGNED
    NOT
    NULL
    DEFAULT
    0
    );
    Query
    OK,
    0
    rows
    affected
    (0.00
    sec)
    mysql>
    INSERT
    INTO
    SalesSummary
    ->
    (proct_name,
    total_sales,
    avg_unit_price,
    total_units_sold)
    ->
    VALUES
    ->
    ('cucumber',
    100.25,
    90,
    2);
    mysql>
    SELECT
    *
    FROM
    SalesSummary;
    +--------------+-------------+----------------+------------------+
    |
    proct_name
    |
    total_sales
    |
    avg_unit_price
    |
    total_units_sold
    |
    +--------------+-------------+----------------+------------------+
    |
    cucumber
    |
    100.25
    |
    90.00
    |
    2
    |
    +--------------+-------------+----------------+------------------+
    1
    row
    in
    set
    (0.00
    sec)
    mysql>
    DROP
    TABLE
    SalesSummary;
    mysql>
    SELECT
    *
    FROM
    SalesSummary;
    ERROR
    1146:
    Table
    'TUTORIALS.SalesSummary'
    doesn't
    exist

    mysql 怎么查看 临时表空间使用情况

    if (select object_ID('tempdb..#BaseInfoFK')) >0 drop table #BaseInfoFK
    select a.* into #BaseInfoFK from (select * from table)a#BaseInfoFK是临时表的名一定要加#

    mysql 怎么查看 临时表空间使用情况

    if (select object_ID('tempdb..#BaseInfoFK')) >0 drop table #BaseInfoFK
    select a.* into #BaseInfoFK from (select * from table)a#BaseInfoFK是临时表的名一定要加#

    sql临时表创建后要手动删除的么!

    临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。如果你使用PHP脚本来创建MySQL临时表,那每当PHP脚本执行完成后,该临时表也会自动销毁。

    删除MySQL 临时表

    默认情况下,当你断开与数据库的连接后,临时表就会自动被销毁。当然你也可以在当前MySQL会话使用 DROP TABLE 命令来手动删除临时表。

    以下是手动删除临时表的实例:

    from 树懒学堂 - 一站式数据知识平台

    sql临时表创建后要手动删除的么!

    临时表只在当前连接可见,当关闭连接时,Mysql会自动删除表并释放所有空间。如果你使用PHP脚本来创建MySQL临时表,那每当PHP脚本执行完成后,该临时表也会自动销毁。

    删除MySQL 临时表

    默认情况下,当你断开与数据库的连接后,临时表就会自动被销毁。当然你也可以在当前MySQL会话使用 DROP TABLE 命令来手动删除临时表。

    以下是手动删除临时表的实例:

    from 树懒学堂 - 一站式数据知识平台

    为什么在mysql存储过程中创建的临时表不能自动销毁

    临时表

    可以创建本地临时表和全局临时表。本地临时表仅在当前会话中可见,而全局临时表在所有会话中都可见。临时表不能分区。

    本地临时表的名称前面有一个数字符号 (#table_name),而全局临时表的名称前面有两个数字符号
    (##table_name)。

    除非使用 DROP TABLE 显式删除临时表,否则临时表将在退出其作用域时由系统自动删除:

    当存储过程完成时,将自动删除在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。

    所有其他本地临时表在当前会话结束时都将被自动删除。

    为什么在mysql存储过程中创建的临时表不能自动销毁

    临时表

    可以创建本地临时表和全局临时表。本地临时表仅在当前会话中可见,而全局临时表在所有会话中都可见。临时表不能分区。

    本地临时表的名称前面有一个数字符号 (#table_name),而全局临时表的名称前面有两个数字符号
    (##table_name)。

    除非使用 DROP TABLE 显式删除临时表,否则临时表将在退出其作用域时由系统自动删除:

    当存储过程完成时,将自动删除在存储过程中创建的本地临时表。由创建表的存储过程执行的所有嵌套存储过程都可以引用此表。但调用创建此表的存储过程的进程无法引用此表。

    所有其他本地临时表在当前会话结束时都将被自动删除。

    mysql怎么实现事务级别的临时表

    MySQL 需要创建隐式临时表来解决某些类型的查询。往往查询的排序阶段需要依赖临时表。例如,当您使用 GROUP BY,ORDER BY 或DISTINCT 时。这样的查询分两个阶段执行:首先是收集数据并将它们放入临时表中,然后是在临时表上执行排序。
    对于某些 UNION 语句,不能合并的 VIEW,子查询时用到派生表,多表 UPDATE 以及其他一些情况,还需要使用临时表。如果临时表很小,可以到内存中创建,否则它将在磁盘上创建。MySQL 在内存中创建了一个表,如果它变得太大,就会被转换为磁盘上存储。内存临时表的最大值由 tmp_table_size 或 max_heap_table_size 值定义,以较小者为准。MySQL 5.7 中的默认大小为 16MB。如果运行查询的数据量较大,或者尚未查询优化,则可以增加该值。设置阈值时,请考虑可用的 RAM 大小以及峰值期间的并发连接数。你无法无限期地增加变量,因为在某些时候你需要让 MySQL 使用磁盘上的临时表。
    注意:如果涉及的表具有 TEXT 或 BLOB 列,则即使大小小于配置的阈值,也会在磁盘上创建临时表。

    mysql怎么实现事务级别的临时表

    MySQL 需要创建隐式临时表来解决某些类型的查询。往往查询的排序阶段需要依赖临时表。例如,当您使用 GROUP BY,ORDER BY 或DISTINCT 时。这样的查询分两个阶段执行:首先是收集数据并将它们放入临时表中,然后是在临时表上执行排序。
    对于某些 UNION 语句,不能合并的 VIEW,子查询时用到派生表,多表 UPDATE 以及其他一些情况,还需要使用临时表。如果临时表很小,可以到内存中创建,否则它将在磁盘上创建。MySQL 在内存中创建了一个表,如果它变得太大,就会被转换为磁盘上存储。内存临时表的最大值由 tmp_table_size 或 max_heap_table_size 值定义,以较小者为准。MySQL 5.7 中的默认大小为 16MB。如果运行查询的数据量较大,或者尚未查询优化,则可以增加该值。设置阈值时,请考虑可用的 RAM 大小以及峰值期间的并发连接数。你无法无限期地增加变量,因为在某些时候你需要让 MySQL 使用磁盘上的临时表。
    注意:如果涉及的表具有 TEXT 或 BLOB 列,则即使大小小于配置的阈值,也会在磁盘上创建临时表。

    显示全文