天天看點

[MySQL5.7] 5.7版本針對臨時表的優化

盡量臨時表在實際線上場景中很少會去顯式使用,但在某些運維場景還是需要到的,在mysql5.7中,專門針對臨時表做了些優化;大概掃了下代碼,把一些要點及關鍵函數記錄下。

#獨立的tmp表空間,預設在data目錄下建立一個命名為ibtmp1的臨時表表空間;對于非壓縮臨時表,表空間内容存放到ibtmp1下面;對于壓縮表,依然會為其在tmp目錄下建立ibd檔案;

#server啟動時會删除之前的ibtmp檔案并重建(函數srv_open_tmp_tablespace)

#臨時表空間使用全局變量srv_tmp_space(5.7裡所有對表空間的管理的代碼被重構成類tablespace)

#無需為臨時表記錄redo log,因為臨時表不做crash recovery;是以在針對臨時表的大量操作直接disable redo (dict_disable_redo_if_temporary)

#臨時表專用的復原段,復原段同樣被記錄到臨時表空間ibtmp1下面(trx_sys_create_noredo_rsegs); 降低和其他實體表的undo log存儲産生競争

盡管臨時表無需做crash recovery,但依然要為其建立undo log表空間,因為可能在事務執行的過程中,需要復原到某個savepoint;

臨時表的undo log無需寫redo (實體表的undo是需要寫redo的)

128個復原段中的32個復原段(srv_tmp_undo_logs)專門預留給臨時表操作(復原段trx_rsegs_t被分為兩類:m_redo及m_noredo)

針對purge操作,也做了修改,采用一個優先隊列來進行操作(具體見函數trxundorsegsiterator::set_next(),  purge_sys->purge_queue, 在函數trx_purge_rseg_get_next_history_log中往隊列加undo,建立臨時表復原段調用trx_sys_create_noredo_rsegs)

其他相關函數:trx_sysf_rseg_find_free,查找復原段(get_next_redo_rseg及get_next_noredo_rseg, trx_assign_rseg_low)

對undo的修改詳細見該patch: http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5832

#臨時表的定義可以存放在記憶體,無需持久化到磁盤;

無需将臨時表的中繼資料資訊寫入到系統表(對于臨時表,create_table_def直接調用dict_build_tablespace && dict_table_add_to_cache

建立索引時同樣區分對待(row_create_index_for_mysql)

其他相關函數:dict_build_index_def,dict_create_index_tree,dict_recreate_index_tree(include/dict0crea.h),這些函數用于對表中繼資料進行操作而無需更新系統表

#降低對臨時表的鎖限制,因為臨時表隻對目前client可見;

例如無需對更新臨時表的二級索引頁設定trx id, 不做可見性判斷(lock_clust_rec_cons_read_sees, lock_sec_rec_cons_read_sees, lock_sec_rec_read_check_and_lock),不會去加innodb層表鎖 (lock_table)

甚至對臨時表而言記錄鎖也是多餘的。

#避免對臨時表使用change buffer.  另外在ibtmp表空間中的臨時表也不為其配置設定ibuf  bitmap page(fsp_fill_free_list)

#增加了一個新的information schema表innodb_temp_table_info來顯示臨時表資訊

root@test 12:41:54>create temporary table t1 (a int);

query ok, 0 rows affected (0.00 sec)

root@test 12:42:17>create temporary table t2 (a int) row_format=compressed;

root@test 12:42:26>select * from information_schema.innodb_temp_table_info;

+———-+————–+——–+——-+———————-+—————+

| table_id | name         | n_cols | space | per_table_tablespace | is_compressed |

|       63 | #sql7e20_7_1 |      4 |    65 | true                 | true          |

|       62 | #sql7e20_7_0 |      4 |    62 | false                | false         |

2 rows in set (0.00 sec)

代碼的修改包含在以下幾個patch中:

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5150

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5456

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5832

建立ibtmp的diff包含在另外一個大diff中(尼瑪完全沒法看啊。。。)

http://bazaar.launchpad.net/~mysql/mysql-server/5.7/revision/5112

官方部落格上的性能資料:

create/drop臨時表的性能:

[MySQL5.7] 5.7版本針對臨時表的優化

臨時表的dml性能:

[MySQL5.7] 5.7版本針對臨時表的優化

——————–

ref:

官方部落格的介紹紹:https://blogs.oracle.com/mysqlinnodb/entry/https_blogs_oracle_com_mysqlinnodb

mysql5.7.3源代碼

 ############

updated @ 2014-11-27,補充下官方相關總結(目前版本:5.7.5)

innodb temporary table performance