新特性解讀 | MySQL 8.0 Temptable 引擎介紹
原創作者: 楊濤濤
提到MySQL臨時表,我們都很熟悉了,一般來說,分為兩類:
1. MySQL 臨時表引擎,名字叫做 Memory。比如
create table tmp1(id int, str1 varchar(100) ) engine = memory;
由引數max_heap_table_size 來控制,超過報錯。
2. 非臨時表的引擎,這裡又分為兩類:
- 使用者自定義的臨時表,比如:
create temporary table (id int, str1 varchar(100) );
- SQL執行過程中產生的內部臨時表,比如:UNION , 聚合類ORDER BY,派生表,大物件欄位的查詢,子查詢或者半連線的固化等等場景。
那麼這兩種臨時表的計數器通常用 show global status like '%tmp_%tables%' 來檢視。比如
mysql> show status like '%tmp_%tables%';` `+-------------------------+-------+` `| Variable_name | Value |` `+-------------------------+-------+` `| Created_tmp_disk_tables | 0 |` `| Created_tmp_tables | 0 |` `+-------------------------+-------+` `2 rows in set (0.00 sec)
以上結果分別代表,只建立磁碟上的臨時表計數以及臨時表的總計數。這兩個計數器由引數 tmp_table_size 和 max_heap_table_size 兩個取最小值來控制。
那在 MySQL 5.7 之前,這個 SQL 執行中產生的臨時表是 MYISAM,而且只能是 MYISAM。那 MySQL 從 5.7 開始提供了引數 Internal_tmp_mem_storage_engine 來定義內部的臨時表引擎,可選值為 MYISAM 和 INNODB 。當然這裡我們選擇 INNODB 。並且把內部的臨時表預設儲存在臨時表空間 ibtmp1 **(可以用引數 innodb_temp_data_file_path 設定大小以及步長等)**下。當然這裡我們得控制下 ibtmp1 的大小,要不然一個爛SQL就把磁碟整爆了。
但是MySQL 5.7 之前都沒有解決如下問題:
-
VARCHAR的變長儲存。那就是如果臨時表的欄位定義是 VARCHAR(200),那麼對映到記憶體裡處理的欄位變為CHAR(200)。假設 VARCHAR(200) 就存裡一個字元 "Y", 那豈不是很大的浪費。
-
大物件的預設磁碟儲存,比如 TEXT,BLOB, JSON等,不管裡面存放了啥,直接轉化為磁碟儲存。
MySQL 8.0 開始,專門實現了一個臨時表的引擎 TempTable , 解決了 VARCHAR欄位的邊長儲存以及大物件的記憶體儲存。由變數 interal_tmp_mem_storage_engine來控制,可選值為 TempTable(預設)和 Memory;新引擎的大小由引數temp_table_max_ram 來控制,預設為1G。超過了則儲存在磁碟上(ibtmp1)。並且計數器由效能字典的表 memory_summary_global_by_event_name 來儲存。
mysql> SELECT * FROM performance_schema. memory_summary_global_by_event_name WHERE event_name like '%temptable%'\G
*************************** 1. row ***************************
EVENT_NAME: **memory/temptable/physical_disk**
COUNT_ALLOC: 0
COUNT_FREE: 0
SUM_NUMBER_OF_BYTES_ALLOC: 0
SUM_NUMBER_OF_BYTES_FREE: 0
LOW_COUNT_USED: 0
CURRENT_COUNT_USED: 0
HIGH_COUNT_USED: 0
LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 0
HIGH_NUMBER_OF_BYTES_USED: 0
*************************** 2. row ***************************
EVENT_NAME: **memory/temptable/physical_ram**
COUNT_ALLOC: 1
COUNT_FREE: 0
SUM_NUMBER_OF_BYTES_ALLOC: 1048576
SUM_NUMBER_OF_BYTES_FREE: 0
LOW_COUNT_USED: 0
CURRENT_COUNT_USED: 1
HIGH_COUNT_USED: 1
LOW_NUMBER_OF_BYTES_USED: 0
CURRENT_NUMBER_OF_BYTES_USED: 1048576
HIGH_NUMBER_OF_BYTES_USED: 1048576
2 rows in set (0.03 sec)
以上 memory/temptable/physical_disk 代表放入磁碟上的臨時表計數情況。
memory/temptable/physical_ram 代表放入記憶體的臨時表計數情況。
那總結下MySQL 8.0 引入的 TempTable 引擎:
-
預設內部臨時表引擎。
-
支援變長字元型別的實際儲存。
-
設定變數 temp_table_max_ram 來控制實際儲存記憶體區域