MEMORY
儲存引擎(先前稱為 HEAP
)建立特殊用途的表格,其內容儲存在記憶體中。由於資料容易受到損毀、硬體問題或斷電的影響,因此這些表格僅應用作臨時工作區域或從其他表格提取資料的唯讀快取。
表 18.4 MEMORY 儲存引擎功能
功能 | 支援 |
---|---|
B 樹索引 | 是 |
備份/時間點復原(在伺服器中實作,而不是在儲存引擎中。) | 是 |
叢集資料庫支援 | 否 |
叢集索引 | 否 |
壓縮資料 | 否 |
資料快取 | 不適用 |
加密資料 | 是(透過加密函式在伺服器中實作。) |
外部索引鍵支援 | 否 |
全文搜尋索引 | 否 |
地理空間資料類型支援 | 否 |
地理空間索引支援 | 否 |
雜湊索引 | 是 |
索引快取 | 不適用 |
鎖定粒度 | 表格 |
MVCC | 否 |
複寫支援(在伺服器中實作,而不是在儲存引擎中。) | 有限(請參閱本節後續的討論。) |
儲存限制 | RAM |
T 樹索引 | 否 |
交易 | 否 |
更新資料字典的統計資料 | 是 |
正在尋找部署使用 MEMORY
儲存引擎處理重要、高可用性或頻繁更新資料的應用程式的開發人員,應考慮 NDB Cluster 是否是更好的選擇。MEMORY
引擎的典型使用案例包含以下特性:
涉及暫時性、非關鍵資料的操作,例如工作階段管理或快取。當 MySQL 伺服器停止或重新啟動時,
MEMORY
表格中的資料會遺失。用於快速存取和低延遲的記憶體儲存。資料量可以完全放入記憶體中,而不會導致作業系統換出虛擬記憶體頁面。
唯讀或大部分唯讀的資料存取模式(有限的更新)。
NDB Cluster 提供與 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.21 節「複製和 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
值。
您也可以在 CREATE TABLE
陳述式中為 MEMORY
資料表指定 MAX_ROWS
資料表選項,以提供有關您計劃在其中儲存的列數的提示。這不會讓資料表的大小超出 max_heap_table_size
值,該值仍會作為最大資料表大小的約束。為了能夠彈性地使用 MAX_ROWS
,請將 max_heap_table_size
設定為至少與您希望每個 MEMORY
資料表能夠成長的值一樣高。
在 https://forums.mysql.com/list.php?92 上有一個專用於 MEMORY
儲存引擎的論壇。