MySQL 臨時表在咱們須要保存一些臨時數據時是很是有用的。臨時表只在當前鏈接可見,當關閉鏈接時,Mysql會自動刪除表並釋放全部空間。 html
臨時表在MySQL 3.23版本中添加,若是你的MySQL版本低於 3.23版本就沒法使用MySQL的臨時表。不過如今通常不多有再使用這麼低版本的MySQL數據庫服務了。 java
MySQL臨時表只在當前鏈接可見,若是你使用PHP腳原本建立MySQL臨時表,那每當PHP腳本執行完成後,該臨時表也會自動銷燬。 mysql
若是你使用了其餘MySQL客戶端程序鏈接MySQL數據庫服務器來建立臨時表,那麼只有在關閉客戶端程序時纔會銷燬臨時表,固然你也能夠手動銷燬。 面試
如下展現了使用MySQL 臨時表的簡單實例,如下的SQL代碼能夠適用於PHP腳本的mysql_query()函數。 sql
>mysql> CREATE TEMPORARY TABLE SalesSummary ( -> product_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 -> (product_name, total_sales, avg_unit_price, total_units_sold) -> VALUES -> ('cucumber', 100.25, 90, 2); mysql> SELECT * FROM SalesSummary; +--------------+-------------+----------------+------------------+ | product_name | total_sales | avg_unit_price | total_units_sold | +--------------+-------------+----------------+------------------+ | cucumber | 100.25 | 90.00 | 2 | +--------------+-------------+----------------+------------------+ 1 row in set (0.00 sec)
當你使用 SHOW TABLES命令顯示數據表列表時,你將沒法看到 SalesSummary表。 數據庫
若是你退出當前MySQL會話,再使用 SELECT命令來讀取原先建立的臨時表數據,那你會發現數據庫中沒有該表的存在,由於在你退出時該臨時表已經被銷燬了。 數組
默認狀況下,當你斷開與數據庫的鏈接後,臨時表就會自動被銷燬。固然你也能夠在當前MySQL會話使用 DROP TABLE 命令來手動刪除臨時表。 性能優化
如下是手動刪除臨時表的實例: 服務器
mysql> CREATE TEMPORARY TABLE SalesSummary ( -> product_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 -> (product_name, total_sales, avg_unit_price, total_units_sold) -> VALUES -> ('cucumber', 100.25, 90, 2); mysql> SELECT * FROM SalesSummary; +--------------+-------------+----------------+------------------+ | product_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 'RUNOOB.SalesSummary' doesn't exist
當工做在很是大的表上時,你可能偶爾須要運行不少查詢得到一個大量數據的小的子集,不是對整個表運行這些查詢,而是讓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的鏈接後系統會自動刪除臨時表中的數據,可是這隻限於用下面語句創建的表:
定義字段:
CREATE TEMPORARY TABLE tmp_table ( name VARCHAR(10) NOT NULL, value INTEGER NOT NULL )
直接將查詢結果導入臨時表
CREATE TEMPORARY TABLE tmp_table SELECT * FROM table_name
另外mysql也容許你在內存中直接建立臨時表,由於是在內存中全部速度會很快,語法以下:
CREATE TEMPORARY TABLE tmp_table ( name VARCHAR(10) NOT NULL, value INTEGER NOT NULL ) TYPE = HEAP
從上面的分析能夠看出臨時表的數據是會被清空的,你斷開了鏈接就會被自動清空,可是你程序中不可能每發行一次sql就鏈接一次數據庫吧(若是是這樣的話,那就會出現你擔憂的問題,若是不是就沒有問題),由於只有斷開數據庫鏈接纔會被清空數據,在一個數據庫鏈接裏面發行屢次sql的話系統是不會自動清空臨時表數據的。
只有在當前鏈接狀況下, TEMPORARY 表纔是可見的。當鏈接關閉時, TEMPORARY 表被自動取消。這意味着兩個不一樣的鏈接可使用相同的臨時表名稱,同時兩個臨時表不會互相沖突,也不與原有的同名的非臨時表衝突。(原有的表被隱藏,直到臨時表被取消時爲止。)必須擁有 CREATE TEMPORARY TABLES 權限,才能建立臨時表。能夠經過指定 ENGINE|TYPE = MEMORY; 來指定建立內存臨時表。
若是表已存在,則使用關鍵詞 IF NOT EXISTS 能夠防止發生錯誤。注意,原有表的結構與 CREATE TABLE 語句中表示的表的結構是否相同,這一點沒有驗證。註釋:若是在 CREATE TABLE...SELECT 語句中使用 IF NOT EXISTS ,則不論表是否已存在,由 SELECT 部分選擇的記錄都會被插入。
DROP TEMPORARY TABLE 語句只取消 TEMPORARY 表,語句不會終止正在進行中的事務。在採用鏈接池的狀況下,爲防止屢次 CREATE 、 DROP TEMPORARY TABLE 帶來的性能瓶頸,可使用 CREATE IF NOT EXISTS + TRUNCATE TABLE 的方式來提高性能。
臨時表支持主鍵、索引指定。在鏈接非臨時表查詢能夠利用指定主鍵或索引來提高性能。
CREATE PROCEDURE sp_test_tt(IN i_chars VARCHAR(50),OUT o_counts BIGINT) BEGIN create temporary table if not exists tmpTable – 不存在則建立臨時表 ( objChk varchar(255) primary key, ModelName varchar(50), Operator varchar(500), PModelName varchar(50) ); truncate TABLE tmpTable; -- 使用前先清空臨時表。 insert into tmpTable values(i_chars,i_chars,i_chars,i_chars); insert into tmpTable values(i_chars,i_chars,i_chars,i_chars); -- 語句1 select * from tmpTable; -- 語句2 select count(*) into o_counts from tmpTable; -- 語句3 END;
上述代碼語句 1 返回臨時表中全部數據,語句 2 將總記錄數寫入輸出參數。 truncate 語句放在 create 以後,而不是整個存儲過程最後,緣由在於隨後的語句 1 插入一樣的值,二臨時表 PK 校驗將產生一個錯誤,則存儲過程最終異常結束。綜合異常處理,能夠以下修改,以在每次存儲過程調用完畢後清除臨時表。
再來看一個例子:
CREATE PROCEDURE sp_test_tt(IN i_chars VARCHAR(50),OUT o_counts BIGINT) BEGIN create temporary table if not exists tmpTable ( objChk varchar(255) primary key, ModelName varchar(50), Operator varchar(500), PModelName varchar(50) ) ENGINE = MEMORY; begin declare exit handler for sqlwarning,NOT FOUND,SQLEXCEPTION set o_counts=-1; insert into tmpTable values(i_chars,i_chars,i_chars,i_chars); select * from tmpTable; -- 語句1 select count(*) into o_counts from tmpTable; end; truncate TABLE tmpTable; -- 語句2 END;
雖然上述代碼語句 2 最後 truncate table 清空了所有臨時表數據,但前面語句 1 select 的數據結果集不會被清除。已經過 java 程序驗證。
臨時表能夠解決二維數組輸出的問題。可是,大批量的數據插入只能由程序採用循環來作。某些特殊狀況下的輸入數組,例如選擇好的一組待刪除數據的 ID 的輸入,也只能利用循環來作。臨時表也不適用於須要三維數組的狀況。
經過CREATE TEMPORARY TABLE 建立的臨時表,這種臨時表稱爲外部臨時表。這種臨時表只對當前用戶可見,當前會話結束的時候,該臨時表會自動關閉。這種臨時表的命名與非臨時表能夠同名(同名後非臨時表將對當前會話不可見,直到臨時表被刪除)。
內部臨時表是一種特殊輕量級的臨時表,用來進行性能優化。這種臨時表會被MySQL自動建立並用來存儲某些操做的中間結果。這些操做可能包括在優化階段或者執行階段。這種內部表對用戶來講是不可見的,可是經過EXPLAIN或者SHOW STATUS能夠查看MYSQL是否使用了內部臨時表用來幫助完成某個操做。內部臨時表在SQL語句的優化過程當中扮演着很是重要的角色, MySQL中的不少操做都要依賴於內部臨時表來進行優化。可是使用內部臨時表須要建立表以及中間數據的存取代價,因此用戶在寫SQL語句的時候應該儘可能的去避免使用臨時表。
內部臨時表有兩種類型:一種是HEAP臨時表,這種臨時表的全部數據都會存在內存中,對於這種表的操做不須要IO操做。另外一種是OnDisk臨時表,顧名思義,這種臨時表會將數據存儲在磁盤上。OnDisk臨時表用來處理中間結果比較大的操做。若是HEAP臨時表存儲的數據大於MAX_HEAP_TABLE_SIZE(詳情請參考MySQL手冊中系統變量部分),HEAP臨時表將會被自動轉換成OnDisk臨時表。OnDisk臨時表在5.7中能夠經過INTERNAL_TMP_DISK_STORAGE_ENGINE系統變量選擇使用MyISAM引擎或者InnoDB引擎。
內存表:
session 1
$ mysql -uroot
root@(none) 10:05:06>use test
Database changed
root @test 10:06:06>CREATE TABLE tmp_memory (i INT) ENGINE = MEMORY;
Query OK, 0 rows affected (0.00 sec)
root @test 10:08:46>insert into tmp_memory values (1);
Query OK, 1 row affected (0.00 sec)
root @test 10:08:46>
session2
$ mysql -uroot test
root @test 10:05:12>CREATE TABLE tmp_memory (i INT) ENGINE = MEMORY;
ERROR 1050 (42S01): Table 'tmp_memory' already exists
root@test 10:16:27>select * from tmp_memory;
+------+
| i |
+------+
| 1 |
+------+
row in set (0.00 sec)
1. 多個session,建立表的名字不能同樣
2. 一個session建立會話後,對其餘session也是可見的
3. data目錄下只有tmp_memory.frm ,表結構放在磁盤上,數據放在內存中
4. mysql 重啓或者關閉後內存表裏的數據會丟失,可是表結構仍然存在
5. 能夠建立索引,刪除索引,支持惟一索引
6. 不影響主備,主庫上插入的數據,備庫也能夠查到
7. show tables 看獲得表
臨時表:
session1
$ mysql -uroot test
root@test 10:30:18>CREATE TEMPORARY TABLE tmp_table (name VARCHAR(10) NOT NULL,value INTEGER NOT NULL);
Query OK, 0 rows affected (0.05 sec)
root@test 10:31:54>select * from tmp_table;
+--------+-------+
| name | value |
+--------+-------+
| aaaaaa | 10 |
+--------+-------+
row in set (0.00 sec)
session2
root@test 10:20:13> CREATE TEMPORARY TABLE tmp_table (name VARCHAR(10) NOT NULL,value INTEGER NOT NULL);
Query OK, 0 rows affected (0.02 sec)
root@test 10:30:39>insert into tmp_table values ('bbbbbbb',10);
Query OK, 1 row affected (0.01 sec)
root@test 10:31:33>select * from tmp_table;
+---------+-------+
| name | value |
+---------+-------+
| bbbbbbb | 10 |
+---------+-------+
row in set (0.00 sec)
root@test 10:31:43>exit
Bye
[1 Single:MS-Master db152011.sqa.cm6: mysql ~ ]
$ mysql -uroot test
root@test 10:32:17>select * from tmp_table;
ERROR 1146 (42S02): Table 'test.tmp_table' doesn't exist
root@test 10:32:22>
root@test 10:32:23>
1. 建立的表的名字能夠同樣
2. 表結構和數據都放在內存中
3. 會話消失表結構和數據都消失
4. 能夠建立索引,刪除索引
5. 主庫建立的表,備庫查不到,
6. show tables 看不到表
使用內存表須要注意的事項
1. 內存表須要本身delete數據或者drop表;須要drop權限,這點比較危險
2. 內存表的表結構是保存在磁盤上的,若是多個session使用同一個表名,會存在衝突;若是不須要使用表名,若是使用一次都須要建立表結構,到時候會有不少小文件存在,不利於db的維護,dba清理表也有風險;
基於以上不適合用內存表
1. 臨時表是會話級別的,即便多個session建立的表名同樣,都相互不影響
2. 會話消失,全部的都消失,這點很不利於應用排查問題
另外這兩個都須要消耗額外的內存空間,雖然db端能夠忍受,可是不太可控;DB端還有這個參數:
max_tmp_tables 一個客戶能同時保持打開的臨時表的最大數量,這個值默認32,能夠根據須要調整此值
About Me
.............................................................................................................................................
● 本文做者:小麥苗,部份內容整理自網絡,如有侵權請聯繫小麥苗刪除
● 本文在itpub(http://blog.itpub.net/26736162/abstract/1/)、博客園(http://www.cnblogs.com/lhrbest)和我的微信公衆號(xiaomaimiaolhr)上有同步更新
● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/
● 本文博客園地址:http://www.cnblogs.com/lhrbest
● 本文pdf版、我的簡介及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/
● 數據庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/
● DBA寶典今日頭條號地址:http://www.toutiao.com/c/user/6401772890/#mid=1564638659405826
.............................................................................................................................................
● QQ羣號:230161599(滿)、618766405
● 微信羣:可加我微信,我拉你們進羣,非誠勿擾
● 聯繫我請加QQ好友(646634621),註明添加原因
● 於 2017-12-01 09:00 ~ 2017-12-31 22:00 在魔都完成
● 文章內容來源於小麥苗的學習筆記,部分整理自網絡,如有侵權或不當之處還請諒解
● 版權全部,歡迎分享本文,轉載請保留出處
.............................................................................................................................................
● 小麥苗的微店:https://weidian.com/s/793741433?wfr=c&ifr=shopdetail
● 小麥苗出版的數據庫類叢書:http://blog.itpub.net/26736162/viewspace-2142121/
.............................................................................................................................................
使用微信客戶端掃描下面的二維碼來關注小麥苗的微信公衆號(xiaomaimiaolhr)及QQ羣(DBA寶典),學習最實用的數據庫技術。
小麥苗的微信公衆號 小麥苗的DBA寶典QQ羣2 《DBA筆試面寶典》讀者羣 小麥苗的微店
.............................................................................................................................................
來自 「 ITPUB博客 」 ,連接:http://blog.itpub.net/26736162/viewspace-2149312/,如需轉載,請註明出處,不然將追究法律責任。