文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (US Ltr) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 參考手冊  /  替代儲存引擎  /  MEMORY 儲存引擎

18.3 MEMORY 儲存引擎

MEMORY 儲存引擎(先前稱為 HEAP)建立特殊用途的表格,其內容儲存在記憶體中。由於資料容易受到損毀、硬體問題或斷電的影響,因此這些表格僅應用作臨時工作區域或從其他表格提取資料的唯讀快取。

表 18.4 MEMORY 儲存引擎功能

功能 支援
B 樹索引
備份/時間點復原(在伺服器中實作,而不是在儲存引擎中。)
叢集資料庫支援
叢集索引
壓縮資料
資料快取 不適用
加密資料 是(透過加密函式在伺服器中實作。)
外部索引鍵支援
全文搜尋索引
地理空間資料類型支援
地理空間索引支援
雜湊索引
索引快取 不適用
鎖定粒度 表格
MVCC
複寫支援(在伺服器中實作,而不是在儲存引擎中。) 有限(請參閱本節後續的討論。)
儲存限制 RAM
T 樹索引
交易
更新資料字典的統計資料

何時使用 MEMORY 或 NDB Cluster

正在尋找部署使用 MEMORY 儲存引擎處理重要、高可用性或頻繁更新資料的應用程式的開發人員,應考慮 NDB Cluster 是否是更好的選擇。MEMORY 引擎的典型使用案例包含以下特性:

  • 涉及暫時性、非關鍵資料的操作,例如工作階段管理或快取。當 MySQL 伺服器停止或重新啟動時,MEMORY 表格中的資料會遺失。

  • 用於快速存取和低延遲的記憶體儲存。資料量可以完全放入記憶體中,而不會導致作業系統換出虛擬記憶體頁面。

  • 唯讀或大部分唯讀的資料存取模式(有限的更新)。

NDB Cluster 提供與 MEMORY 引擎相同的功能,並具有更高的效能等級,並提供 MEMORY 無法使用的其他功能。

  • 資料列層級鎖定和多執行緒操作,以降低用戶端之間的爭用。

  • 即使在包含寫入的陳述式組合中,也具有可擴展性。

  • 用於資料持久性的選用磁碟支援操作。

  • 無共用架構和多主機操作,沒有單點故障,可實現 99.999% 的可用性。

  • 跨節點自動資料分配;應用程式開發人員不需要製作自訂分片或分割區解決方案。

  • 支援 MEMORY 不支援的可變長度資料類型(包括 BLOBTEXT)。

分割區

MEMORY 表格無法分割區。

效能特性

MEMORY 的效能受到單執行緒執行和處理更新時表格鎖定額外負荷導致的爭用限制。當負載增加時,這會限制可擴展性,特別是對於包含寫入的陳述式組合。

儘管 MEMORY 表格進行記憶體內處理,但對於一般用途查詢或在讀/寫工作負載下,它們不一定比忙碌伺服器上的 InnoDB 表格快。特別是,執行更新涉及的表格鎖定可能會減慢多個工作階段同時使用 MEMORY 表格的速度。

根據對 MEMORY 表格執行的查詢類型,您可以將索引建立為預設雜湊資料結構(用於根據唯一索引鍵尋找單個值),或是一般用途的 B 樹資料結構(用於所有涉及相等、不相等或範圍運算子(例如小於或大於)的查詢)。以下各節說明建立這兩種索引的語法。常見的效能問題是在 B 樹索引更有效率的工作負載中使用預設雜湊索引。

MEMORY 表格的特性

MEMORY 儲存引擎不會在磁碟上建立任何檔案。表格定義儲存在 MySQL 資料字典中。

MEMORY 表格具有以下特性:

  • MEMORY 表格的空間以小區塊配置。表格使用 100% 動態雜湊進行插入。不需要溢位區域或額外的索引鍵空間。不需要額外的空間來存放可用清單。刪除的資料列會放入連結清單中,並在您將新資料插入表格時重複使用。MEMORY 表格也沒有與雜湊表格中的刪除加插入相關的常見問題。

  • MEMORY 表格使用固定長度的資料列儲存格式。使用固定長度儲存可變長度類型,例如 VARCHAR

  • MEMORY 表格不能包含 BLOBTEXT 資料行。

  • MEMORY 包含對 AUTO_INCREMENT 資料行的支援。

  • TEMPORARY MEMORY 表格在所有用戶端之間共用,就像任何其他非 TEMPORARY 表格一樣。

MEMORY 表格的 DDL 操作

若要建立 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 TABLETRUNCATE TABLE 生效的值,將作為該資料表生命週期所使用的值。伺服器重新啟動也會將現有 MEMORY 資料表的最大大小設定為全域 max_heap_table_size 值。您可以在本節稍後描述的方式中設定個別資料表的大小。

索引

MEMORY 儲存引擎同時支援 HASHBTREE 索引。您可以透過新增 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 資料表不受儲存轉換的影響,而內部臨時資料表則會受影響

載入資料

若要在 MySQL 伺服器啟動時填入 MEMORY 資料表,您可以使用 init_file 系統變數。例如,您可以將 INSERT INTO ... SELECTLOAD DATA 等陳述式放入檔案中,以從永久性資料來源載入資料表,並使用 init_file 來命名該檔案。請參閱 第 7.1.8 節「伺服器系統變數」第 15.2.9 節「LOAD DATA 陳述式」

MEMORY 資料表與複製

當複製來源伺服器關閉並重新啟動時,其 MEMORY 資料表會變成空的。若要將此效果複製到複本,來源在啟動後首次使用給定的 MEMORY 資料表時,會記錄一個事件,通知複本必須清空該資料表,方法是將該資料表的 TRUNCATE TABLE 陳述式寫入二進位記錄。當複本伺服器關閉並重新啟動時,其 MEMORY 資料表也會變成空的,並且會將 TRUNCATE TABLE 陳述式寫入其自身的二進位記錄,該記錄會傳遞給任何下游複本。

當您在複製拓撲中使用 MEMORY 資料表時,在某些情況下,來源上的資料表和複本上的資料表可能會有所不同。如需有關如何處理這些情況以防止過時的讀取或錯誤的資訊,請參閱 第 19.5.1.21 節「複製和 MEMORY 資料表」

管理記憶體使用量

伺服器需要足夠的記憶體來維護所有同時使用的 MEMORY 資料表。

如果您從 MEMORY 資料表中刪除個別的列,記憶體不會被回收。只有在刪除整個資料表時,才會回收記憶體。先前用於已刪除列的記憶體會在同一個資料表中重新用於新的列。若要釋放 MEMORY 資料表不再需要其內容時使用的所有記憶體,請執行 DELETETRUNCATE 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 儲存引擎的論壇。