MEMORY
儲存引擎 (先前稱為 HEAP
) 會建立特殊用途的表格,其內容會儲存在記憶體中。由於資料容易受到當機、硬體問題或電源中斷的影響,因此這些表格僅能用作臨時工作區域或從其他表格提取資料的唯讀快取。
表 18.4 MEMORY 儲存引擎功能
功能 | 支援 |
---|---|
B 樹索引 | 是 |
備份/時間點復原 (在伺服器中實作,而不是在儲存引擎中實作。) | 是 |
叢集資料庫支援 | 否 |
叢集索引 | 否 |
壓縮資料 | 否 |
資料快取 | 不適用 |
加密資料 | 是 (透過加密函數在伺服器中實作。) |
外部鍵支援 | 否 |
全文搜尋索引 | 否 |
地理空間資料類型支援 | 否 |
地理空間索引支援 | 否 |
雜湊索引 | 是 |
索引快取 | 不適用 |
鎖定精細度 | 表格 |
MVCC | 否 |
複寫支援 (在伺服器中實作,而不是在儲存引擎中實作。) | 有限制 (請參閱本節稍後的討論。) |
儲存限制 | RAM |
T 樹索引 | 否 |
交易 | 否 |
更新資料字典的統計資料 | 是 |
希望部署應用程式使用 MEMORY
儲存引擎來處理重要、高可用性或經常更新的資料的開發人員,應該考慮 NDB 叢集是否是更好的選擇。MEMORY
引擎的典型使用案例包含以下特性
涉及暫時性、非關鍵資料 (例如工作階段管理或快取) 的操作。當 MySQL 伺服器停止或重新啟動時,
MEMORY
表格中的資料會遺失。用於快速存取和低延遲的記憶體內儲存。資料量可以完全放入記憶體中,而不會導致作業系統將虛擬記憶體頁面換出。
唯讀或大部分唯讀的資料存取模式 (有限的更新)。
NDB 叢集提供與 MEMORY
引擎相同的功能,並具有更高的效能等級,並提供 MEMORY
無法提供的其他功能
MEMORY
效能受到單執行緒執行和處理更新時表格鎖定額外負荷所導致的競爭所限制。當負載增加時,這會限制可擴展性,特別是對於包含寫入的陳述式組合而言。
儘管 MEMORY
表格會進行記憶體內處理,但在繁忙的伺服器上、一般用途查詢或讀/寫工作負載下,它們不一定比 InnoDB
表格快。尤其是,執行更新時涉及的表格鎖定會減慢多個工作階段同時使用 MEMORY
表格的速度。
根據對 MEMORY
表格執行的查詢種類,您可以將索引建立為預設的雜湊資料結構 (用於根據唯一索引鍵查詢單一值),或是一般用途的 B 樹資料結構 (用於所有涉及相等、不相等或範圍運算子 (例如小於或大於) 的查詢)。以下章節說明建立這兩種索引的語法。常見的效能問題是在 B 樹索引更有效率的工作負載中使用預設雜湊索引。
MEMORY
儲存引擎不會在磁碟上建立任何檔案。表格定義會儲存在 MySQL 資料字典中。
MEMORY
表格具有以下特性
MEMORY
表格的空間是以小區塊配置的。表格在插入時使用 100% 的動態雜湊。不需要溢位區域或額外的索引鍵空間。不需要額外空間來放置可用清單。刪除的資料列會放入連結清單中,並在您將新資料插入表格時重複使用。MEMORY
表格也沒有一般與雜湊表格中的刪除加上插入相關聯的問題。MEMORY
表格使用固定長度的資料列儲存格式。可變長度類型 (例如VARCHAR
) 會使用固定長度儲存。MEMORY
包含對AUTO_INCREMENT
資料行的支援。非
TEMPORARY
MEMORY
表格會與所有用戶端共用,就像任何其他非TEMPORARY
表格一樣。
若要建立 MEMORY
表格,請在 CREATE TABLE
陳述式上指定子句 ENGINE=MEMORY
。
CREATE TABLE t (i INT) ENGINE = MEMORY;
如引擎名稱所示,MEMORY
表格會儲存在記憶體中。它們預設使用雜湊索引,這使得它們對於單一值查詢非常快,並且對於建立臨時表格非常有用。但是,當伺服器關閉時,儲存在 MEMORY
表格中的所有資料列都會遺失。表格本身會繼續存在,因為它們的定義會儲存在 MySQL 資料字典中,但當伺服器重新啟動時,它們會是空的。
此範例示範您可能如何建立、使用和移除 MEMORY
表格
mysql> CREATE TABLE test ENGINE=MEMORY
SELECT ip,SUM(downloads) AS down
FROM log_table GROUP BY ip;
mysql> SELECT COUNT(ip),AVG(down) FROM test;
mysql> DROP TABLE test;
MEMORY
表格的最大容量受限於 max_heap_table_size
系統變數,其預設值為 16MB。若要對 MEMORY
表格強制執行不同的容量限制,請變更此變數的值。對於 CREATE TABLE
或後續的 ALTER TABLE
或 TRUNCATE TABLE
所生效的值,將會用於該表格的整個生命週期。重新啟動伺服器也會將現有 MEMORY
表格的最大容量設定為全域的 max_heap_table_size
值。您可以如同本節稍後所述,設定個別表格的大小。
MEMORY
儲存引擎同時支援 HASH
和 BTREE
索引。您可以透過新增 USING
子句來為給定的索引指定其中一種,如下所示
CREATE TABLE lookup
(id INT, INDEX USING HASH (id))
ENGINE = MEMORY;
CREATE TABLE lookup
(id INT, INDEX USING BTREE (id))
ENGINE = MEMORY;
關於 B 樹和雜湊索引的一般特性,請參閱 第 10.3.1 節「MySQL 如何使用索引」。
MEMORY
表格每個表格最多可有 64 個索引、每個索引 16 個欄位,以及 3072 位元組的最大金鑰長度。
如果 MEMORY
表格的雜湊索引具有高度的金鑰重複 (許多索引項目包含相同的值),則影響金鑰值的表格更新和所有刪除操作將會明顯變慢。這種減速的程度與重複程度成正比(或與索引基數成反比)。您可以使用 BTREE
索引來避免這個問題。
MEMORY
表格可以有非唯一金鑰。(這是雜湊索引實作中不常見的功能。)
索引的欄位可以包含 NULL
值。
MEMORY
表格的內容會儲存在記憶體中,這是 MEMORY
表格與伺服器在處理查詢時動態建立的內部暫存表格所共有的屬性。然而,這兩種表格的不同之處在於,MEMORY
表格不受儲存轉換的限制,而內部暫存表格則會受限。
如果內部暫存表格變得太大,伺服器會自動將其轉換為磁碟上的儲存空間,如 第 10.4.4 節「MySQL 中內部暫存表格的使用」中所述。
使用者建立的
MEMORY
表格永遠不會轉換為磁碟表格。
若要在 MySQL 伺服器啟動時填入 MEMORY
表格,您可以使用 init_file
系統變數。例如,您可以將諸如 INSERT INTO ... SELECT
或 LOAD DATA
之類的陳述式放入檔案中,以從持久資料來源載入表格,並使用 init_file
來命名該檔案。請參閱 第 7.1.8 節「伺服器系統變數」和 第 15.2.9 節「LOAD DATA 陳述式」。
當複製來源伺服器關閉並重新啟動時,其 MEMORY
表格會變為空白。為了將此效果複製到複本,來源第一次在啟動後使用給定的 MEMORY
表格時,它會記錄一個事件,通知複本必須透過在二進位日誌中寫入該表格的 TRUNCATE TABLE
陳述式來清空該表格。當複本伺服器關閉並重新啟動時,其 MEMORY
表格也會變為空白,並且它會將 TRUNCATE TABLE
陳述式寫入其本身的二進位日誌,該日誌會傳遞給任何下游複本。
當您在複製拓撲中使用 MEMORY
表格時,在某些情況下,來源上的表格和複本上的表格可能會有所不同。若要瞭解如何處理每種情況以防止過時的讀取或錯誤,請參閱 第 19.5.1.22 節「複製和 MEMORY 表格」。
伺服器需要足夠的記憶體來維護所有同時在使用的 MEMORY
表格。
如果您從 MEMORY
表格中刪除個別列,則記憶體不會被回收。只有當整個表格被刪除時,記憶體才會被回收。先前用於已刪除列的記憶體會被重新用於同一個表格內的新列。若要在您不再需要 MEMORY
表格的內容時釋放它使用的所有記憶體,請執行 DELETE
或 TRUNCATE TABLE
以移除所有列,或使用 DROP TABLE
完全移除表格。若要釋放已刪除列使用的記憶體,請使用 ALTER TABLE ENGINE=MEMORY
強制重新建置表格。
MEMORY
表格中一列所需的記憶體是使用以下運算式計算的
SUM_OVER_ALL_BTREE_KEYS(max_length_of_key + sizeof(char*) * 4)
+ SUM_OVER_ALL_HASH_KEYS(sizeof(char*) * 2)
+ ALIGN(length_of_row+1, sizeof(char*))
ALIGN()
表示一個進位因數,使列長度成為 char
指標大小的整數倍。sizeof(char*)
在 32 位元電腦上為 4,在 64 位元電腦上為 8。
如前所述,max_heap_table_size
系統變數設定 MEMORY
表格最大容量的限制。若要控制個別表格的最大容量,請在建立每個表格之前設定此變數的階段作業值。(除非您打算將該值用於所有用戶端建立的 MEMORY
表格,否則請勿變更全域 max_heap_table_size
值。)以下範例建立兩個 MEMORY
表格,其最大容量分別為 1MB 和 2MB
mysql> SET max_heap_table_size = 1024*1024;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t1 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.01 sec)
mysql> SET max_heap_table_size = 1024*1024*2;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE t2 (id INT, UNIQUE(id)) ENGINE = MEMORY;
Query OK, 0 rows affected (0.00 sec)
如果伺服器重新啟動,這兩個表格都會還原為伺服器的全域 max_heap_table_size
值。
您也可以在 MEMORY
表格的 CREATE TABLE
陳述式中指定 MAX_ROWS
表格選項,以提供您計畫在其中儲存的列數提示。這並不會讓表格成長超出 max_heap_table_size
值,後者仍然充當最大表格大小的限制。為了能夠彈性地使用 MAX_ROWS
,請將 max_heap_table_size
設定為至少與您希望每個 MEMORY
表格能夠成長的值一樣高。
專門討論 MEMORY
儲存引擎的論壇位於 https://forums.mysql.com/list.php?92。