15.3 MEMORY 存储引擎

MEMORY存储引擎(以前称为HEAP)创建特殊用途的 table,其内容存储在内存中。由于数据容易受到崩溃,硬件问题或电源中断的影响,因此只能将这些 table 用作临时工作区或只读缓存,以存储从其他 table 中提取的数据。

table15.4 MEMORY 存储引擎功能

FeatureSupport
B-tree indexesYes
备份/时间点恢复 (在服务器中而不是在存储引擎中实现.)Yes
集群数据库支持No
Clustered indexesNo
Compressed dataNo
Data cachesN/A
Encrypted data是(通过加密功能在服务器中实现.)
外键支持No
全文搜索索引No
地理空间数据类型支持No
地理空间索引支持No
Hash indexesYes
Index cachesN/A
Locking granularityTable
MVCCNo
复制支持 (在服务器中而不是在存储引擎中实现.)受限(请参阅本节后面的讨论.)
Storage limitsRAM
T-tree indexesNo
TransactionsNo
更新数据字典的统计信息Yes

何时使用 MEMORY 或 NDB 群集

希望部署使用MEMORY存储引擎处理重要,高度可用或经常更新的数据的应用程序的开发人员,应考虑 NDB Cluster 是否是更好的选择。 MEMORY引擎的典型用例涉及以下 Feature:

  • 涉及瞬态,非关键数据的操作,例如会话 Management 或缓存。当 MySQL 服务器停止或重新启动时,MEMORYtable 中的数据将丢失。

  • 内存中存储可实现快速访问和低延迟。数据量可以完全容纳在内存中,而不会导致 os 换出虚拟内存页面。

  • 只读或只读的数据访问模式(有限的更新)。

NDB 群集具有与MEMORY引擎相同的功能,并且具有更高的性能水平,并提供了MEMORY不可用的其他功能:

  • 行级锁定和多线程操作可减少 Client 端之间的争用。

  • 即使包含写的语句混合也具有可伸缩性。

  • 可选的磁盘支持操作,可确保数据持久性。

  • 无共享架构和多主机操作,没有单点故障,可实现 99.999%的可用性。

  • 跨节点自动数据分发;应用程序开发人员无需制定自定义分片或分区解决方案。

  • MEMORY不支持可变长度数据类型(包括BLOBTEXT)。

Performance Characteristics

MEMORY性能受到单线程执行和处理更新时 table 锁开销所导致的争用的限制。当负载增加时,这会限制可伸缩性,尤其是对于包含写入的语句混合。

尽管对MEMORYtable 进行了内存内处理,但它们不一定要比繁忙服务器上的InnoDBtable,用于通用查询或在读/写工作负载下要快。特别是,执行更新所涉及的 table 锁定会减慢来自多个会话的MEMORYtable 的并发使用。

根据对MEMORYtable 执行的查询的类型,您可以将索引创建为默认哈希数据结构(用于基于唯一键查找单个值)或通用 B 树数据结构(用于各种类型)涉及相等,不相等或范围运算符(例如小于或大于)的查询。以下各节说明了创建两种索引的语法。一个常见的性能问题是在 B 树索引更有效的工作负载中使用默认哈希索引。

MEMORYtable 的 Feature

MEMORY存储引擎将每个 table 与一个磁盘文件关联,该磁盘文件存储 table 定义(而不是数据)。文件名以 table 名开头,extensions 为.frm

MEMORYtable 具有以下 Feature:

  • MEMORY个 table 的空间以小块分配。table 对插入使用 100%动态哈希。不需要溢出区域或额外的密钥空间。空闲列 table 不需要额外的空间。删除的行放在链接列 table 中,当您在 table 中插入新数据时可以重复使用。 MEMORYtable 也没有与哈希 table 中的删除和插入通常相关的问题。

  • MEMORYtable 使用固定长度的行存储格式。可变长度类型(例如VARCHAR)使用固定长度存储。

  • MEMORYtable 不能包含BLOBTEXT列。

  • MEMORY支持AUTO_INCREMENT列。

  • 与所有其他非TEMPORARYtable 一样,非TEMPORARY MEMORYtable 在所有 Client 端之间共享。

MEMORYtable 的 DDL 操作

要创建MEMORYtable,请在CREATE TABLE语句上指定子句ENGINE=MEMORY

CREATE TABLE t (i INT) ENGINE = MEMORY;

如引擎名称所示,MEMORY个 table 存储在内存中。默认情况下,它们使用哈希索引,这使它们对于单值查找非常快,对于创建临时 table 非常有用。但是,当服务器关闭时,存储在MEMORYtable 中的所有行都会丢失。这些 table 本身 continue 存在,因为它们的定义存储在磁盘上的.frm文件中,但是在服务器重新启动时它们为空。

本示例说明了如何创建,使用和删除MEMORYtable:

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;

MEMORYtable 的最大大小受max_heap_table_size系统变量的限制,系统变量的默认值为 16MB。要对MEMORYtable 实施不同的大小限制,请更改此变量的值。 CREATE TABLE或后续的ALTER TABLETRUNCATE TABLE的有效值是 table 生命周期内使用的值。服务器重新启动还会将现有MEMORYtable 的最大大小设置为全局max_heap_table_size值。您可以按照本节后面的说明设置单个 table 的大小。

Indexes

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 树和哈希索引的一般 Feature,请参见第 8.3.1 节“ MySQL 如何使用索引”

MEMORYtable 每个 table 最多可以有 64 个索引,每个索引最多可以有 16 列,最大键长为 3072 字节。

如果MEMORYtable 哈希索引具有高度的键重复性(许多索引条目包含相同的值),则影响键值的 table 更新和所有删除操作的速度将显着降低。此减速的程度与重复程度成正比(或与索引基数成反比)。您可以使用BTREE索引来避免此问题。

MEMORYtable 可以具有非唯一键。 (这是哈希索引实现的罕见功能.)

被索引的列可以包含NULL个值。

用户创建的临时 table

MEMORYtable 的内容存储在内存中,这是MEMORYtable 与服务器在处理查询时动态创建的内部临时 table 共享的属性。但是,两种类型的 table 的区别在于MEMORYtable 不进行存储转换,而内部临时 table 是:

Loading Data

要在 MySQL 服务器启动时填充MEMORYtable,可以使用init_file系统变量。例如,您可以将诸如插入...选择LOAD DATA之类的语句放入文件中以从持久数据源加载 table,并使用init_file命名文件。参见第 5.1.7 节“服务器系统变量”第 13.2.6 节“ LOAD DATA 语句”

MEMORYtable 和复制

当复制源服务器关闭并重新启动时,其MEMORYtable 将为空。为了将此效果复制到副本中,源在启动后首次使用给定的MEMORYtable 时,会记录一个事件,该事件通知副本必须为此写DELETE或(从 MySQL 5.7.32 起)TRUNCATE TABLE语句来清空该 table。table 到二进制日志。当副本服务器关闭并重新启动时,其MEMORYtable 也将变为空,并将DELETE或(从 MySQL 5.7.32 起)TRUNCATE TABLE语句写入其自己的二进制日志,该语句将传递给任何下游副本。

在复制拓扑中使用MEMORYtable 时,在某些情况下,源上的 table 和副本上的 table 将有所不同。有关处理每种情况以防止陈旧读取或错误的信息,请参见第 16.4.1.20 节“复制和内存 table”

Management 内存使用

服务器需要足够的内存来维护所有正在使用的MEMORYtable。

如果从MEMORYtable 中删除单个行,则不会回收内存。仅在删除整个 table 时才回收内存。先前用于已删除行的内存将重新用于同一 table 中的新行。要在不再需要MEMORYtable 的内容时释放其使用的所有内存,请执行DELETETRUNCATE TABLE删除所有行,或使用DROP TABLE一起删除该 table。要释放已删除的行使用的内存,请使用ALTER TABLE ENGINE=MEMORY强制重建 table。

MEMORYtable 中一行所需的内存使用以下 table 达式计算:

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()table 示向上舍入因子,导致行长度是char指针大小的精确倍数。 sizeof(char*)在 32 位计算机上为 4,在 64 位计算机上为 8.

如前所述,max_heap_table_size系统变量设置MEMORYtable 的最大大小的限制。要控制单个 table 的最大大小,请在创建每个 table 之前设置此变量的会话值。 (除非您打算将该值用于所有 Client 端创建的MEMORYtable,否则不要更改全局max_heap_table_size值。)以下示例创建两个MEMORYtable,最大大小分别为 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)

如果服务器重新启动,则两个 table 都将还原为服务器的全局max_heap_table_size值。

您还可以在MEMORYtable 的CREATE TABLE语句中指定MAX_ROWStable 选项,以提示您计划存储在其中的行数。这不能使 table 增长到超过max_heap_table_size值,该值仍然是最大 table 大小的约束。为了最大程度地灵活使用MAX_ROWS,请将max_heap_table_size至少设置为希望每个MEMORYtable 能够增长到的值。

Additional Resources

https://forums.mysql.com/list.php?92提供了一个专门讨论MEMORY存储引擎的论坛。