A、臨時表再斷開於mysql的連接后系統會自動刪除臨時表中的數據,但是這只限於用下面語句建立的表:
1)定義字段
CREATE TEMPORARY TABLE tmp_table (
name VARCHAR(10) NOT NULL,
time date NOT NULL
)
更高級點就是:
create temporary TABLE `temtable` (
`jws` varchar(100) character set utf8 collate utf8_bin NOT NULL,
`tzlb` varchar(100) character set utf8 collate utf8_bin NOT NULL,
`uptime` date NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1″
連編碼方式都規定了。。呵呵,以防亂碼啊。
2)直接將查詢結果導入臨時表
CREATE TEMPORARY TABLE tmp_table SELECT * FROM table_name
B、另外mysql也允許你在內存中直接創建臨時表,因為是在內存中所有速度會很快,語法如下:
CREATE TEMPORARY TABLE tmp_table (
name VARCHAR(10) NOT NULL,
value INTEGER NOT NULL
) TYPE = HEAP
那如何將查詢的結果存入已有的表呢?
1、可以使用A中第二個方法
2、使用insert into temtable (select a,b,c,d from tablea)”;
首先,臨時表只在當前連接可見,當關閉連接時,Mysql會自動刪除表並釋放所有空間。因此在不同的連接中可以創建同名的臨時表,並且操作屬於本連接的臨時表。
創建臨時表的語法與創建表語法類似,不同之處是增加關鍵字TEMPORARY,如:
CREATE TEMPORARY TABLE 表名 (…. )
臨時表使用有一些限制條件:
* 臨時表在 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字節的
MySQL如何使用臨時表??
【臨時表存儲】
MySQL臨時表分為“內存臨時表”和“磁盤臨時表”,其中內存臨時表使用MySQL的MEMORY存儲引擎,磁盤臨時表使用MySQL的MyISAM存儲引擎;
一般情況下,MySQL會先創建內存臨時表,但內存臨時表超過配置指定的值后,MySQL會將內存臨時表導出到磁盤臨時表。
【使用臨時表的場景】
1)ORDER BY子句和GROUP BY子句不同,
例如:ORDERY BY price GROUP BY name;
2)在JOIN查詢中,ORDER BY或者GROUP BY使用了不是第一個表的列
例如:SELECT * from TableA, TableB ORDER BY TableA.price GROUP by TableB.name
3)ORDER BY中使用了DISTINCT關鍵字
ORDERY BY DISTINCT(price)
4)SELECT語句中指定了SQL_SMALL_RESULT關鍵字
SQL_SMALL_RESULT的意思就是告訴MySQL,結果會很小,請直接使用內存臨時表,不需要使用索引排序
SQL_SMALL_RESULT必須和GROUP BY、DISTINCT或DISTINCTROW一起使用
一般情況下,我們沒有必要使用這個選項,讓MySQL服務器選擇即可。
【直接使用磁盤臨時表的場景】
1)表包含TEXT或者BLOB列;
2)GROUP BY 或者 DISTINCT 子句中包含長度大於512字節的列;
3)使用UNION或者UNION ALL時,SELECT子句中包含大於512字節的列;
【臨時表相關配置】
tmp_table_size:指定系統創建的內存臨時表最大大小;
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_tmp_table_size
max_heap_table_size: 指定用戶創建的內存表的最大大小;
http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_max_heap_table_size
注意:最終的系統創建的內存臨時表大小是取上述兩個配置值的最小值。
【表的設計原則】
使用臨時表一般都意味着性能比較低,特別是使用磁盤臨時表,性能更慢,因此我們在實際應用中應該盡量避免臨時表的使用。
如果實在無法避免,也應該盡量避免使用磁盤臨時表。
常見的方法有:
1)創建索引:在ORDER BY或者GROUP BY的列上創建索引,這樣可以避免使用臨時表;
2)分拆很長的列,可以避免使用磁盤臨時表:一般情況下,TEXT、BLOB,大於512字節的字符串,基本上都是為了顯示信息,而不會用於查詢條件,因此表設計的時候,應該將這些列獨立到另外一張表。
【如何判斷使用了臨時表?】
使用explain查看執行計划,Extra列看到Using temporary就意味着使用了臨時表。
MySQL官方手冊:
http://dev.mysql.com/doc/refman/5.1/en/internal-temporary-tables.html