1. 程式人生 > 其它 >查詢優化手段之臨時表

查詢優化手段之臨時表

create temporary table temp_t like t1;
alter table temp_t add index(b);
insert into temp_t select * from t2 where b>=1 and b<=2000;
select * from t1 join temp_t on (t1.b=temp_t.b);

臨時表有什麼特徵,直接用普通表是不是也可以呢?臨時表和記憶體表有什麼區別?

  • 記憶體表,指的是使用 Memory 引擎的表,建表語法是 create table … engine=memory。這種表的資料都儲存在記憶體裡,系統重啟的時候會被清空,但是表結構還在。除了這兩個特性看上去比較“奇怪”外,從其他的特徵上看,它就是一個正常的表。

  • 而臨時表,可以使用各種引擎型別 。如果是使用 InnoDB 引擎或者 MyISAM 引擎的臨時表,寫資料的時候是寫到磁碟上的。當然,臨時表也可以使用 Memory 引擎。

臨時表的特性

1.建表語法是 create temporary table …。
2.一個臨時表只能被建立它的 session 訪問,對其他執行緒不可見。所以,圖中 session A 建立的臨時表 t,對於 session B 就是不可見的。
3.臨時表可以與普通表同名。
4.session A 內有同名的臨時表和普通表的時候,show create 語句,以及增刪改查語句訪問的是臨時表。
5.show tables 命令不顯示臨時表。

由於臨時表只能被建立它的session訪問,所以在這個session結束的時候,會自動刪除臨時表。正是這個特性,臨時表就特別適合我們文章開頭的join優化這種場景。

原因主要包括以下兩個方面:

1.不同 session 的臨時表是可以重名的,如果有多個 session 同時執行 join 優化,不需要擔心表名重複導致建表失敗的問題。
2.不需要擔心資料刪除問題。如果使用普通表,在流程執行過程中客戶端發生了異常斷開,或者資料庫發生異常重啟,還需要專門來清理中間過程中生成的資料表。而臨時表由於會自動回收,所以不需要這個額外的操作。

臨時表的應用

由於不用擔心執行緒之間的重名衝突,臨時表經常會被用在複雜查詢的優化過程中。其中,分庫分表系統的跨庫查詢就是一個典型的使用場景。

  • 為什麼不同執行緒可以建立同名的臨時表,這是怎麼做到的呢?
create temporary table temp_t(id int primary key)engine=innodb;

MySQL要給這個InnoDB表建立一個frm檔案儲存表結構定義,還要有地方儲存表資料。
這個frm檔案放在臨時檔案目錄下,檔名的字尾是.frm

如果當前的 binlog_format=row,那麼跟臨時表有關的語句,就不會記錄到 binlog 裡。也就是說,只在 binlog_format=statment/mixed 的時候,binlog 中才會記錄臨時表的操作。

建立臨時表的語句會傳到備庫執行,因此備庫的同步執行緒就會建立這個臨時表。主庫線上程退出的時候,會自動刪除臨時表,但是備庫同步執行緒是持續在執行的,所以,這時候我們就需要在主庫上再寫一個 DROP TEMPORARY TABLE 傳給備庫執行。

總結: 臨時表建表語法create temporary table ,和普通的表不一樣,和記憶體表也不一樣。記憶體表資料儲存到記憶體裡,重啟會丟失,臨時表會寫入到磁碟。臨時表只對自己的session中可見,session結束後自動刪除表結構和表資料。適用場景是分庫分表,查詢到的資料在臨時表中做聚合。臨時表可以重名,實際的儲存檔名有執行緒id,在記憶體中表的命名有table_ref_key,是由庫名加表名加serverid+執行緒id組成。bin log設定為row模式,臨時表不會同步到備庫中,設定為statement模式,會同步到備庫中。