在某些情況下,伺服器會在處理語句時建立內部暫存表格。使用者無法直接控制何時發生這種情況。
伺服器會在下列情況下建立暫存表格:
評估
UNION
語句,但有一些例外情況稍後描述。評估某些視圖,例如使用
TEMPTABLE
演算法、UNION
或彙總的視圖。評估衍生表(請參閱第 15.2.15.8 節,「衍生表」)。
評估通用表式(請參閱第 15.2.20 節,「WITH (通用表式)」)。
為子查詢或半聯結實體化建立的表格(請參閱第 10.2.2 節,「最佳化子查詢、衍生表、視圖參考和通用表式」)。
評估包含
ORDER BY
子句和不同的GROUP BY
子句的語句,或者對於ORDER BY
或GROUP BY
包含來自聯結佇列中第一個資料表以外的資料表的欄位的情況。DISTINCT
與ORDER BY
結合使用可能需要暫存表格。對於使用
SQL_SMALL_RESULT
修飾符的查詢,MySQL 會使用記憶體中的暫存表格,除非查詢也包含(稍後描述的)需要磁碟儲存的元素。為了評估從同一個資料表選取並插入資料的
INSERT ... SELECT
語句,MySQL 會建立一個內部暫存表格來保存來自SELECT
的列,然後將這些列插入目標資料表。請參閱第 15.2.7.1 節,「INSERT ... SELECT 語句」。評估多表
UPDATE
陳述式。評估
GROUP_CONCAT()
或COUNT(DISTINCT)
運算式。視窗函數的評估(請參閱第 14.20 節,視窗函數)會根據需要使用暫存表。
若要判斷陳述式是否需要暫存表,請使用 EXPLAIN
並檢查 Extra
欄位,查看是否顯示 Using temporary
(請參閱第 10.8.1 節,使用 EXPLAIN 優化查詢)。EXPLAIN
不一定會針對衍生或具體化的暫存表顯示 Using temporary
。對於使用視窗函數的陳述式,使用 FORMAT=JSON
的 EXPLAIN
始終會提供有關視窗步驟的資訊。如果視窗函數使用暫存表,則會在每個步驟中指出。
某些查詢條件會阻止使用記憶體中的暫存表,在這種情況下,伺服器會改用磁碟上的表。
對於符合某些條件的 UNION
陳述式,伺服器不使用暫存表。相反,它僅保留執行結果欄位類型轉換所需之暫存表建立的資料結構。該表並未完全實例化,也沒有寫入或讀取任何列;列直接發送到用戶端。這樣做的結果是減少了記憶體和磁碟需求,並縮短了第一列發送到用戶端之前的延遲,因為伺服器不需要等到執行最後一個查詢區塊。EXPLAIN
和最佳化工具追蹤輸出反映了此執行策略:UNION RESULT
查詢區塊不存在,因為該區塊對應於從暫存表中讀取的部分。
這些條件使 UNION
符合條件,可以在不使用暫存表的情況下進行評估。
聯集是
UNION ALL
,而不是UNION
或UNION DISTINCT
。沒有全域
ORDER BY
子句。聯集不是
{INSERT | REPLACE} ... SELECT ...
陳述式的頂層查詢區塊。
內部暫存表可以保存在記憶體中,並由 TempTable
或 MEMORY
儲存引擎處理,或由 InnoDB
儲存引擎儲存在磁碟上。
記憶體內部暫存表的儲存引擎
internal_tmp_mem_storage_engine
變數定義了用於記憶體內部暫存表的儲存引擎。允許的值為 TempTable
(預設值)和 MEMORY
。
設定 internal_tmp_mem_storage_engine
的會話設定需要 SESSION_VARIABLES_ADMIN
或 SYSTEM_VARIABLES_ADMIN
權限。
TempTable
儲存引擎為 VARCHAR
和 VARBINARY
欄位以及其他二進制大型物件類型提供高效的儲存。
以下變數控制 TempTable
儲存引擎的限制和行為
tmp_table_size
:定義由 TempTable 儲存引擎建立的任何單個記憶體內部暫存表的最大大小。當達到tmp_table_size
限制時,MySQL 會自動將記憶體內部暫存表轉換為InnoDB
磁碟上的內部暫存表。預設的tmp_table_size
設定為 16777216 位元組 (16 MiB)。tmp_table_size
限制旨在防止個別查詢消耗過多全域 TempTable 資源,這可能會影響需要 TempTable 資源的並行查詢效能。全域 TempTable 資源由temptable_max_ram
和temptable_max_mmap
設定控制。如果
tmp_table_size
限制小於temptable_max_ram
限制,則記憶體中的暫存表不可能包含超過tmp_table_size
限制允許的更多資料。如果tmp_table_size
限制大於temptable_max_ram
和temptable_max_mmap
限制的總和,則記憶體中的暫存表不可能包含超過temptable_max_ram
和temptable_max_mmap
限制總和的更多資料。temptable_max_ram
:定義TempTable
儲存引擎在開始從記憶體對應檔案分配空間,或在 MySQL 開始使用InnoDB
磁碟上的內部暫存表之前,可以使用的最大 RAM 量,具體取決於您的組態。預設的temptable_max_ram
設定值為伺服器上可用總記憶體的 3%,預設最小值和最大值範圍為 1-4 GB。在 MySQL 8.4 之前,預設值為 1GiB。注意temptable_max_ram
設定不考慮分配給每個使用TempTable
儲存引擎之執行緒的執行緒本地記憶體區塊。執行緒本地記憶體區塊的大小取決於執行緒的首次記憶體配置請求的大小。如果請求小於 1MB(大多數情況下都是如此),則執行緒本地記憶體區塊大小為 1MB。如果請求大於 1MB,則執行緒本地記憶體區塊的大小大致與初始記憶體請求的大小相同。執行緒本地記憶體區塊會保存在執行緒本地儲存中,直到執行緒退出。temptable_use_mmap
:控制當超過temptable_max_ram
限制時,TempTable
儲存引擎是從記憶體對應檔案分配空間,還是 MySQL 使用InnoDB
磁碟上的內部暫存表。預設設定為temptable_use_mmap=OFF
。注意temptable_use_mmap
變數已過時;預期在未來版本的 MySQL 中會移除對它的支援。設定temptable_max_mmap=0
等同於設定temptable_use_mmap=OFF
。temptable_max_mmap
:設定在 MySQL 開始使用InnoDB
磁碟上的內部暫存表之前,TempTable 儲存引擎允許從記憶體對應檔案分配的最大記憶體量。預設設定為 0(停用)。此限制旨在解決記憶體對應檔案在暫存目錄 (tmpdir
) 中使用過多空間的風險。temptable_max_mmap = 0
會停用從記憶體對應檔案分配,有效地停用它們的使用,無論temptable_use_mmap
設定為何。
TempTable
儲存引擎使用記憶體對應檔案受以下規則約束
暫存檔案會在
tmpdir
變數定義的目錄中建立。暫存檔案會在建立和開啟後立即刪除,因此不會保留在
tmpdir
目錄中。當暫存檔案開啟時,暫存檔案佔用的空間會由作業系統保留。當TempTable
儲存引擎關閉暫存檔案,或關閉mysqld
程序時,會回收該空間。資料永遠不會在 RAM 和暫存檔案之間、RAM 內部或暫存檔案之間移動。
如果空間在
temptable_max_ram
定義的限制內可用,則新資料會儲存在 RAM 中。否則,新資料會儲存在暫存檔案中。如果將表格的部分資料寫入暫存檔後,RAM 中有可用空間,則剩餘的表格資料有可能會儲存在 RAM 中。
當對記憶體內暫存表格使用 MEMORY
儲存引擎時(internal_tmp_mem_storage_engine=MEMORY
),如果記憶體內暫存表格變得過大,MySQL 會自動將其轉換為磁碟上的表格。記憶體內暫存表格的最大大小由 tmp_table_size
或 max_heap_table_size
值(以較小者為準)定義。這與使用 CREATE TABLE
明確建立的 MEMORY
表格不同。對於這類表格,只有 max_heap_table_size
變數決定表格可以增長到多大,並且不會轉換為磁碟格式。
磁碟內部暫存表格的儲存引擎
MySQL 9.0 僅對磁碟上的內部暫存表格使用 InnoDB
儲存引擎。(不再支援 MYISAM
儲存引擎用於此目的。)
InnoDB
磁碟上的內部暫存表格建立在預設位於資料目錄中的工作階段暫存表空間中。如需更多資訊,請參閱第 17.6.3.5 節,「暫存表空間」。
當記憶體內的內部暫存表格由 TempTable
儲存引擎管理時,包含 VARCHAR
欄位、VARBINARY
欄位和其他二進位大型物件類型欄位的列,在記憶體中會以儲存格陣列表示,每個儲存格包含一個 NULL
旗標、資料長度以及資料指標。欄位值會依序放置在陣列後方,在單一記憶體區域中,沒有填補。陣列中的每個儲存格使用 16 個位元組的儲存空間。當 TempTable
儲存引擎從記憶體對應檔案配置空間時,也適用相同的儲存格式。
當記憶體內的內部暫存表格由 MEMORY
儲存引擎管理時,會使用固定長度的列格式。VARCHAR
和 VARBINARY
欄位值會填補到最大欄位長度,實際上將它們儲存為 CHAR
和 BINARY
欄位。
磁碟上的內部暫存表格一律由 InnoDB
管理。
當使用 MEMORY
儲存引擎時,陳述式可以先建立記憶體內的內部暫存表格,然後在表格變得過大時將其轉換為磁碟上的表格。在這種情況下,跳過轉換並直接在磁碟上建立內部暫存表格,可能會獲得更好的效能。可以使用 big_tables
變數來強制將內部暫存表格儲存在磁碟上。
當在記憶體或磁碟上建立內部暫存表格時,伺服器會增加 Created_tmp_tables
的值。當在磁碟上建立內部暫存表格時,伺服器會增加 Created_tmp_disk_tables
的值。如果太多內部暫存表格在磁碟上建立,請考慮調整內部暫存表格儲存引擎中描述的引擎特定限制。
由於已知限制,Created_tmp_disk_tables
不會計算在記憶體對應檔案中建立的磁碟暫存表格。預設情況下,TempTable 儲存引擎溢位機制會在記憶體對應檔案中建立內部暫存表格。請參閱內部暫存表格儲存引擎。
可以使用 memory/temptable/physical_ram
和 memory/temptable/physical_disk
Performance Schema 工具來監控 TempTable
從記憶體和磁碟配置的空間。memory/temptable/physical_ram
會報告已配置的 RAM 量。memory/temptable/physical_disk
會報告當記憶體對應檔案用作 TempTable 溢位機制時,從磁碟配置的空間量。如果 physical_disk
工具報告的值不是 0,且記憶體對應檔案用作 TempTable 溢位機制,則表示在某個時間點已達到 TempTable 記憶體限制。可以在 Performance Schema 記憶體摘要表格(例如 memory_summary_global_by_event_name
)中查詢資料。請參閱第 29.12.20.10 節,「記憶體摘要表格」。