您的位置:首页 > 数据库 > MySQL

Mysql temporary table

2015-07-28 16:16 459 查看
Internal Temporary Table


  当我们的SQL语句相对“复杂”,需要MySQL思考更多时,就会出发自身使用internal temp table,比如:语句中有order by或是group by,还有当我们要修改表的一些属性,比如增加加索引或是添加字段,这些都有可能使用到临时表,我们通过explain这个命令输出的extra列可以看到这样的提示using temporary。这类临时表多数都是内存表也就是MEMORY的存在于内存中,当临时表使用的空间大于tmp_table_size参数设置的值时,该临时表的类型就会自动变成MyISAM的表,那么会被存储到磁盘上,很显然当存取数据从内存转变到磁盘上,这个性能的落差将是我们无法容忍的,所以我们要通过观察Created_tmp_disk_tables参数增长的程度来调整tmp_table_size的到小,该参数仅对于memory类型的internal临时表有效。

User-defined Temporary Table

  通过语句CREATE TEMPORARY TABLE XXX 来创建应用所需的临时表。我们自定义的临时表有以下一些特点:

  1. 临时表的存在的周期是当前登录的session有效,断开连接将会被立即删除,也可手动将其drop table,无论以任何类型创建的表,在对应的数据库目录下都没有具体的文件生成,但是所有的DML语句都会被记录(后面会说复制的问题);既然是session有效,那么不同的session间是不能访问别人定义的临时表的,不同session定义的临时表名就可以相同。

  2. 支持多种类型的表:MYISAM、MEMORY、MERGE、INNODB,其中对于内存表,通过max_heap_table_size参数值来控制表的大小;peter曾经测试基于memory的临时表的查询速度要比mysiam的快10到100倍,还发现key_buffer_size对于查询有相当重要的影响,即便应用所有的表都是innodb类型的,设置该参数对于提高查询性能有很大帮助;

  3. 为什么要用它呢?临时表可以将我们之后可能频繁使用到的中间数据集临时保存下来,这样就会提高业务的处理速度,再有就是可以减少程序代码量,将一定的逻辑处理放到数据库上去完成,这之间的代价需要实际去评估;到了5.0以后出现了视图,对于开发人员有多了一种可选择的方法,而视图的定义是可以永久保存到磁盘上的,视图是不能重名的。

  4. 对于临时表的DML操作都会被记录到binlog中,但是前提是binlog的日志格式需要设置为statement模式;主从间对于临时表的操作复制,由于从库slave线程的不恰当关闭,将会导致临时表的复制失败,关闭前需要保证所有的临时表都不处在打开更新的状态,这样再次恢复主从是从库对于临时表的复制才能继续正常进行(想不明白???)

临时表使用有一些限制条件:

  * 临时表在 memory、myisam、merge或者innodb上使用,并且不支持mysql cluster簇);

show tables语句不会列出临时表,在information_schema中也不存在临时表信息;show create table可以查看临时表;

  * 不能使用rename来重命名临时表。但是可以alter table rename代替:

 mysql>ALTER TABLE orig_name RENAME new_name;

  * 可以复制临时表得到一个新的临时表,如:

mysql>create temporary table new_table select * from old_table;

  * 但在同一个query语句中,相同的临时表只能出现一次。如:

可以使用:mysql> select * from temp_tb;

但不能使用:mysql> select * from temp_tb, temp_tb as t;

错误信息: ERROR 1137 (HY000): Can't reopen table: 'temp_tb'

同样相同临时表不能在存储函数中出现多次,如果在一个存储函数里,用不同的别名查找一个临时表多次,或者在这个存储函数里用不同的语句查找,都会出现这个错误。

  * 但不同的临时表可以出现在同一个query语句中,如临时表temp_tb1, temp_tb2:

Mysql> select * from temp_tb1, temp_tb2;

临时表可以手动删除:

DROP TEMPORARY TABLE IF EXISTS temp_tb;

临时表主要用于对大数据量的表上作一个子集,提高查询效率。

在创建临时表时声明类型为HEAP,则Mysql会在内存中创建该临时表,即内存表:如:

CREATE TEMPORARY TABLE 表名 (。。。。) TYPE = HEAP

因为HEAP表存储在内存中,你对它运行的查询可能比磁盘上的临时表快些。如:

mysql> create temporary table temp_tb type='heap' select * from temptb;

Query OK, 0 rows affected, 1 warning (0.01 sec)

Records: 0 Duplicates: 0 Warnings: 0

mysql> show create table temp_tb \G;

*************************** 1. row ***************************

Table: temp_tb

Create Table: CREATE TEMPORARY TABLE `temp_tb` (

`id` int(10) unsigned NOT NULL DEFAULT '0',

`Name` char(20) NOT NULL,

`Age` tinyint(4) NOT NULL

) ENGINE=MEMORY DEFAULT CHARSET=gbk

1 row in set (0.00 sec)

ERROR:

No query specified

可以看出来临时表和内存表的ENGINE 不同,临时表默认的是Mysql指定的默认Engine,而内存表是MEMORY。

官方手册:

As indicated by the name, MEMORY tables are stored in memory. They use hash indexes by default, which makes them very fast, and very useful for creating temporary tables. However, when the server shuts down, all rows stored in MEMORY tables are lost. The tables
themselves continue to exist because their definitions are stored in .frm files on disk, but they are empty when the server restarts.

内存表的建立还有一些限制条件:

MEMORY tables cannot contain BLOB or TEXT columns. HEAP不支持BLOB/TEXT列。

The server needs sufficient memory to maintain all MEMORY tables that are in use at the same time. 在同一时间需要足够的内存.

To free memory used by a MEMORY table when you no longer require its contents, you should execute DELETE or TRUNCATE TABLE, or remove the table altogether using DROP TABLE.为了释放内存,你应该执行DELETE FROM heap_table或DROP TABLE heap_table。

临时表和内存表

临时表主要是为了放一些中间大结果集的一些子集,内存表可以放一些经常频繁使用的数据。

* 临时表:表建在内存里,数据在内存里

* 内存表:表建在磁盘里,数据在内存里

临时表和内存表所使用内存大小可以通过My.cnf中的max_heap_table_size、tmp_table_size指定:

[mysqld]

max_heap_table_size=1024M #内存表容量

tmp_table_size=1024M #临时表容量

当数据超过临时表的最大值设定时,自动转为磁盘表,此时因需要进行IO操作,性能会大大下降,而内存表不会,内存表满后,则会提示数据满错误。

show tables 命令不会显示临时表。

以下是对内存表和临时表之间区别的总结:

内存表:

1.缺省存储引擎为MEMORY

2.可以通过参数max_heap_table_size来设定内存表大小

3.到达max_heap_table_size设定的内存上限后将报错

4.表定义保存在磁盘上,数据和索引保存在内存中

5.不能包含TEXT、BLOB等字段

临时表:

1.缺省存储引擎为MySQL服务器默认引擎,引擎类型只能是:memory(heap)、myisam、merge、innodb(memory临时表由于表的增大可能会转变为myisam临时表)

2.可以通过参数 tmp_table_size 来设定临时表大小。

3.到达tmp_table_size设定的内存上限后将在磁盘上创建临时文件

4.表定义和数据都保存在内存中

5.可以包含TEXT, BLOB等字段

临时表一般比较少用,通常是在应用程序中动态创建或者由MySQL内部根据SQL执行计划需要自己创建。

内存表则大多作为Cache来使用,特别在没有第三方cache使用时。如今随着memcache、NoSQL的流行,越来越少选择使用内存表。

MySQL服务器使用内部临时表

在某些情况下,mysql服务器会自动创建内部临时表。查看查询语句的执行计划,如果extra列显示“using temporary”即使用了内部临时表。内部临时表的创建条件:

* group by 和 order by中的列不相同

* order by的列不是引用from 表列表中 的第一表

* group by的列不是引用from 表列表中 的第一表

* 使用了sql_small_result选项

* 含有distinct 的 order by语句

初始创建内部myisam临时表的条件:

* 表中存在text、blob列

* 在group by中的 列 有超过512字节

* 在distinct查询中的 列 有超过512字节

* 在union、union all联合查询中,select 列 列表中的 列 有超过512字节的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: