在某些情況下,伺服器會在處理陳述式時建立內部暫存表格。使用者無法直接控制何時發生這種情況。
伺服器會在以下情況下建立暫存表格
評估
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
始終會提供有關視窗步驟的資訊。如果視窗函式使用暫存表格,則會針對每個步驟指出。
某些查詢條件會阻止使用記憶體內暫存表格,在這種情況下,伺服器會改用磁碟上的表格
表格中存在
BLOB
或TEXT
資料行。在 MySQL 8.4 中,用於記憶體內部暫存表格的預設儲存引擎TempTable
支援二進位大型物件類型。請參閱內部暫存表格儲存引擎。如果使用
UNION
或UNION ALL
,則在SELECT
清單中存在最大長度大於 512 的字串資料行(二進位字串為位元組,非二進位字串為字元)。SHOW COLUMNS
和DESCRIBE
陳述式使用BLOB
作為某些資料行的類型,因此用於結果的暫存表格為磁碟上的表格。
伺服器不會對符合特定條件的 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
:設定TempTable
儲存引擎在 MySQL 開始使用InnoDB
磁碟上的內部暫存表格之前,允許從記憶體對應檔案配置的最大記憶體量。預設設定為 0(停用)。此限制旨在解決記憶體對應檔案在暫存目錄 (tmpdir
) 中使用過多空間的風險。temptable_max_mmap = 0
會停用從記憶體對應檔案配置,從而有效地停用它們的使用,無論temptable_use_mmap
設定如何。
以下規則控制 TempTable
儲存引擎對記憶體對應檔案的使用
暫存檔案會在
tmpdir
變數定義的目錄中建立。暫存檔案會在建立並開啟後立即刪除,因此不會保留在
tmpdir
目錄中。暫存檔案佔用的空間會在暫存檔案開啟時由作業系統保留。當TempTable
儲存引擎關閉暫存檔案或當mysqld
程序關閉時,空間會被回收。資料永遠不會在 RAM 和暫存檔案之間、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 8.4 僅使用 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
效能綱要工具來監控從記憶體和磁碟配置的 TempTable
空間。memory/temptable/physical_ram
報告配置的 RAM 量。memory/temptable/physical_disk
報告當記憶體對應檔案用作 TempTable 溢位機制時,從磁碟配置的空間量。如果 physical_disk
工具報告的值不是 0,並且記憶體對應檔案用作 TempTable 溢位機制,則表示在某個時間點已達到 TempTable 記憶體限制。可以在效能綱要記憶體摘要表中查詢資料,例如 memory_summary_global_by_event_name
。請參閱第 29.12.20.10 節,「記憶體摘要表」。