在查看MySQL优化的过程中会看到使用临时表,这里就说明一下临时表的用法!
参考博客: https://www.cnblogs.com/duanxz/p/3724120.html
和之前一样理论的东西可能来自这个博客或者官方文档的补充,但是实例都是自己测试的。
MySQL 临时表在我们需要保存一些临时数据时是非常有用的。临时表只在当前连接可见,当关闭连接时,MySQL会自动删除表并释放所有空间。
使用其他MySQL客户端程序连接MySQL数据库服务器来创建临时表,那么只有在关闭客户端程序时才会销毁临时表,当然也可以手动删除。
MySQL中的两种临时表
- 外部临时表:通过CREATE TEMPORARY TABLE 创建的临时表,这种临时表称为外部临时表。这种临时表只对当前用户可见,当前会话结束的时候,该临时表会自动关闭。这种临时表的命名与非临时表可以同名(同名后非临时表将对当前会话不可见,直到临时表被删除)。
- 内部临时表有两种类型:一种是HEAP临时表,这种临时表的所有数据都会存在内存中,对于这种表的操作不需要IO操作。另一种是OnDisk临时表,顾名思义,这种临时表会将数据存储在磁盘上。OnDisk临时表用来处理中间结果比较大的操作。如果HEAP临时表存储的数据大于MAX_HEAP_TABLE_SIZE(详情请参考MySQL手册中系统变量部分),HEAP临时表将会被自动转换成OnDisk临时表。
外部临时表
You can use the TEMPORARY keyword when creating a table. A TEMPORARY table is visible only within the current session, and is dropped automatically when the session is closed. This means that two different sessions can use the same temporary table name without conflicting with each other or with an existing non-TEMPORARY table of the same name. (The existing table is hidden until the temporary table is dropped.)可以使用TEMPORARY关键字创建临时表,临时表仅对当前会话可见,当会话断开的时候临时表自动删除。这意味着两个不同的会话可以使用相同名字的临时表而没有冲突;也可以和非临时表同名,同名的非临时表会被隐藏,知道临时表删除才会出现。
临时表与数据库的关系非常松散,删除数据库不会删除数据库下面的临时表。
外部临时表的使用在之前的一篇博客提到过:https://www.cnblogs.com/wxzhe/p/9767991.html
这里只说明几点需要注意的问题:
- 在同一条sql语句中不能同时关联两次临表
mysql> select * from tmp_tb1, tmp_tb1 as tmptb; ERROR 1137 (HY000): Can't reopen table: 'tmp_tb1' mysql>
- show tables语句不会显示临时表,但是show create table 语句可以查看临时表的建表语句。
mysql> show create table tmp_tb1G *************************** 1. row *************************** Table: tmp_tb1 Create Table: CREATE TEMPORARY TABLE `tmp_tb1` ( `id` int(3) DEFAULT NULL, `name` varchar(6) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> show tables; +------------------+ | Tables_in_mytest | +------------------+ | articles | | hostinfo | | tb1 | | tb2 | | tb3 | | user_stopword | +------------------+ 6 rows in set (0.00 sec) mysql>
- 不能使用rename重命名临时表,可以使用alter table语句。
mysql> rename table tmp_tb1 to tmp_tb2; ERROR 1017 (HY000): Can't find file: './mytest/tmp_tb1.frm' (errno: 2 - No such file or directory)
- 影响使用复制功能。
内部临时表
内部临时表这里,我们先看一下官方文档的描述:在某些情况下,服务器在处理语句的过程中创建内部临时表,这种情况发生时,用户不能直接的控制。
In some cases, the server creates internal temporary tables while processing statements. Users have no direct control over when this occurs.
在下面的情况下,MySQL会使用临时表:
The server creates temporary tables under conditions such as these:【在下面这些情况下,服务器将创建临时表】 Evaluation of UNION statements。【Union联合查询】 Evaluation of some views, such those that use the TEMPTABLE algorithm, UNION, or aggregation.【处理视图,使用了临时表算法】 Evaluation of derived tables 【处理派生表】. Tables created for subquery or semi-join materialization。【子查询或半连接物化创建的表】 Evaluation of statements that contain an ORDER BY clause and a different GROUP BY clause, or for which the ORDER BY or GROUP BY contains columns from tables other than the first table in the join queue.【包含ORDER BY子句和其他GROUP BY子句的语句的计算,或者ORDER BY或GROUP BY包含来自连接队列中第一个表以外的表的列。】 Evaluation of DISTINCT combined with ORDER BY may require a temporary table.【distince结合order by可能需要临时表】 For queries that use the SQL_SMALL_RESULT modifier, MySQL uses an in-memory temporary table, unless the query also contains elements that require on-disk storage.【对于使用SQL_SMALL_RESULT 修饰符的查询,MySQL使用内存中的临时表,除非查询还包含需要磁盘存储的元素】 To evaluate INSERT ... SELECT statements that select from and insert into the same table, MySQL creates an internal temporary table to hold the rows from the SELECT, then inserts those rows into the target table. 【insert ....table select....table语句需要临时表】 Evaluation of multiple-table UPDATE statements.【多表更新】 Evaluation of GROUP_CONCAT() or COUNT(DISTINCT) expressions.
确定语句是否使用临时表,可以使用explain命令查看extra栏的输出是否为use temporary. [对于派生表和物化表不一定显示这样]
When the server creates an internal temporary table (either in memory or on disk), it increments the Created_tmp_tables status variable. If the server creates the table on disk (either initially or by converting an in-memory table) it increments the Created_tmp_disk_tables status variable.
一些查询条件会阻止服务器使用内存临时表而使用磁盘临时表:
- Presence of a BLOB or TEXT column in the table. This includes user-defined variables having a string value because they are treated as BLOB or TEXT columns, depending on whether their value is a binary or nonbinary string, respectively.【不太懂】
- 如果使用union或union all,则在选择列表中存在最大长度大于512(二进制字符串的字节数,非二进制字符串的字符数)的任何字符串列。
- show columns和describe语句使用blob作为某些列的类型,因此用于结果的临时表是磁盘上的表。
These conditions qualify a UNION for evaluation without a temporary table:
- The union is UNION ALL, not UNION or UNION DISTINCT.
- There is no global ORDER BY clause.
- The union is not the top-level query block of an {INSERT | REPLACE} ... SELECT ... statement.
内部临时表可以保存在内中使用memory存储引擎,也可以保存在磁盘上使用innodb或myisam存储引擎。
如果内部临时表被创建为内存中的表,但变得太大,MySQL会自动将其转换为磁盘临时表。内存中临时表的最大大小由tmp_table_size或max_heap_table_size值定义,以较小者为准。这与使用create table显式创建的内存表不同;对于此类表,只有max_heap_table_size变量确定表可以增长的大小,并且不存在到磁盘格式的转换。
internal_tmp_disk_storage_engine参数决定服务器使用磁盘临时表的存储引擎。
mysql> show variables like "internal_tmp_disk_storage_engine"; +----------------------------------+--------+ | Variable_name | Value | +----------------------------------+--------+ | internal_tmp_disk_storage_engine | InnoDB | +----------------------------------+--------+ 1 row in set (0.00 sec)
当使用磁盘临时表存储引擎为innodb时,查询生成的磁盘临时表遵循innodb的行和字段的限制,若是报Row size too large or Too many columns 的错误,可以把磁盘临时表存储引擎更改为myisam。
【待续】