Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  Alternative Storage Engines  /  The MEMORY Storage Engine

18.3 MEMORY 存储引擎

MEMORY 存储引擎(formerly known as HEAP)创建专门用途的表,内容存储在内存中。由于数据易受崩溃、硬件问题或断电影响,因此只将这些表用于临时工作区或从其他表读取数据的只读缓存。

MEMORY 存储引擎特性

Feature Support
B-tree 索引
备份/点时恢复(在服务器中实现,而不是在存储引擎中。)
集群数据库支持
聚簇索引
压缩数据
数据缓存 N/A
加密数据 是(在服务器中通过加密函数实现。)
外键支持
全文搜索索引
地理空间数据类型支持
地理空间索引支持
哈希索引
索引缓存 N/A
锁定粒度
MVCC
复制支持(在服务器中实现,而不是在存储引擎中。) 有限(请参阅本节后面的讨论。)
存储限制 RAM
T-树索引
事务
更新数据字典统计信息

开发者想部署使用MEMORY存储引擎的应用程序,以便在重要、可用或频繁更新数据时考虑NDB集群是否更好。使用MEMORY引擎的一般用例涉及以下特点:

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

  • 内存存储以实现快速访问和低延迟。数据体积可以完全fit在内存中,而不需要操作系统交换虚拟内存页。

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

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

  • 行级锁定和多线程操作,以减少客户端之间的低争用。

  • 即使包含写入语句的语句混合,也可以保持可扩展性。

  • optional磁盘备份操作以确保数据持久性。

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

  • 自动将数据分布到节点上;应用程序开发者不需要编写自定义分区或分片解决方案。

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

分区

MEMORY表不能被分区。

MEMORY性能受到单线程执行和表锁定开销的限制,当处理更新时,这会限制可扩展性,特别是当包含写入语句的语句混合增加时。

尽管MEMORY表进行内存处理,但它们在忙碌服务器上、一般查询或读/写工作负载下不一定比InnoDB表快。在特定情况下,更新时的表锁定可能会 slows down多个会话对MEMORY表的并发使用。

根据对 MEMORY 表的查询类型,您可能创建索引为默认哈希数据结构(用于基于唯一键查找单个值)或通用 B 树数据结构(用于涉及等式、不等式或范围操作符的所有查询)。以下部分展示了创建这两种索引的语法。常见性能问题是使用默认哈希索引在工作负载中,而 B 树索引更高效。

MEMORY 表特性

MySQL 存储引擎不在磁盘上创建任何文件。表定义存储在 MySQL 数据字典中。

MEMORY 表具有以下特性:

  • MEMORY 表的空间分配是小块的。表使用 100% 动态哈希插入数据。没有溢出区或额外键空间需要。没有额外空间用于自由列表。删除的行被放置在链表中,并在您将新数据插入到表时重用。 MEMORY 表也没有与哈希表相关的常见问题,即删除加插入。

  • MEMORY 表使用固定长度行存储格式。可变长度类型,如VARCHAR,使用固定长度存储。

  • MEMORY 表不能包含BLOBTEXT 列。

  • MEMORY支持AUTO_INCREMENT列。

  • TEMPORARYMEMORY表与所有客户端共享,正如任何其他非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 TABLEALTER TABLETRUNCATE TABLE 语句的生效值是该表的整个生命周期。服务器重启也将现有 MEMORY 表的最大大小设置为全局max_heap_table_size 值。你可以根据后续部分中的描述为单个表设置大小。

索引

MEMORY 存储引擎支持 both 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-树和哈希索引的常见特征,请参阅Section 10.3.1, “How MySQL Uses Indexes”

MEMORY 表可以有最多 64 个索引、16 列 per 索引和最大键长度为 3072 字节。

如果哈希索引的MEMORY表具有高程度的键重复(许多索引条目包含相同值),更新该表的键值和所有删除操作将明显变慢。这种 slowdown 的程度与重复程度成正比(或,反比例于索引卡片度)。您可以使用BTREE索引来避免这个问题。

MEMORY表可以具有非唯一键。 (这是哈希索引实现的不常见特性。)

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

用户创建和临时表

MEMORY表的内容存储在内存中,这是MEMORY表与服务器在处理查询时自动创建的内部临时表共享的一种属性。然而,这两种类型的表不同之处在于,MEMORY表不受存储转换的影响,而内部临时表则是:

在 MySQL 服务器启动时,使用 init_file 系统变量可以-populate一个MEMORY表。例如,您可以将语句,如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节,“Replication and MEMORY Tables”

服务器需要足够的内存来维护所有同时使用的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()表示将行长度调整为一个exact的整数倍数,sizeof(char*)在32位机器上为4,在64位机器上为8。

如前所述,max_heap_table_size 系统变量设置了 MEMORY 表的最大大小。要控制每个表的最大大小,设置会话值此变量之前创建每个表。(不要更改全局max_heap_table_size 值,除非你想让该值用于所有客户端创建的 MEMORY 表。)以下示例创建了两个 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 语句中指定 MAX_ROWS 表选项,以提供关于你计划存储在其中的行数的提示。这不启用表超出max_heap_table_size 值的限制,MAX_ROWS 仍然是对最大表大小的约束。为了在使用 MAX_ROWS 时拥有最大的灵活性,请将max_heap_table_size 设置为你想要每个 MEMORY 表能增长到的值至少高于该值。

有一个专门为MEMORY存储引擎的论坛,可以访问https://forums.mysql.com/list.php?92