mysql建立臨時表,將查詢結果插入已有表中

 今天遇到一個很棘手的問題,想臨時存起來一部分數據,而後再讀取。我記得學數據庫理論課老師說能夠建立臨時表,不知道mysql有沒有這樣的功能呢?臨時表在內存之中,讀取速度應該比視圖快一些。而後還須要將查詢的結果存儲到臨時表中。下面是建立臨時表以及插入數據的例子,以供你們參考。html

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″
連編碼方式都規定了。。呵呵,以防亂碼啊。mysql


2)直接將查詢結果導入臨時表
  CREATE TEMPORARY TABLE tmp_table SELECT * FROM table_namesql

B、另外mysql也容許你在內存中直接建立臨時表,由於是在內存中全部速度會很快,語法以下:
  CREATE TEMPORARY TABLE tmp_table (
     name VARCHAR(10) NOT NULL,
     value INTEGER NOT NULL
  ) TYPE = HEAP數據庫

那如何將查詢的結果存入已有的表呢?服務器

一、可使用A中第二個方法函數

二、使用insert into temtable (select a,b,c,d from tablea)」;性能


   首先,臨時表只在當前鏈接可見,當關閉鏈接時,Mysql會自動刪除表並釋放全部空間。所以在不一樣的鏈接中能夠建立同名的臨時表,而且操做屬於本鏈接的臨時表。大數據

        建立臨時表的語法與建立表語法相似,不一樣之處是增長關鍵字TEMPORARY,如:ui

               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

相關文章
相關標籤/搜索