# 16.3 MEMORY 存储引擎

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

表 16.4 内存存储引擎特性

特征 支持
B树索引 是的
备份/时间点恢复(在服务器中实现,而不是在存储引擎中。) 是的
集群数据库支持
聚集索引
压缩数据
数据缓存 不适用
加密数据 是(通过加密功能在服务器中实现。)
外键支持
全文检索索引
地理空间数据类型支持
地理空间索引支持
哈希索引 是的
索引缓存 不适用
锁定粒度 桌子
MVCC
复制支持(在服务器中实现,而不是在存储引擎中。) 有限(参见本节后面的讨论。)
存储限制 内存
T-树索引
交易
更新数据字典的统计信息 是的

# 何时使用 MEMORY 或 NDB Cluster

希望部署使用记忆重要、高可用或经常更新数据的存储引擎应考虑 NDB Cluster 是否是更好的选择。一个典型的用例记忆引擎涉及以下特性:

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

  • 内存存储,可实现快速访问和低延迟。数据量可以完全适合内存,而不会导致操作系统换出虚拟内存页面。

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

    NDB Cluster 提供与记忆引擎具有更高的性能水平,并提供其他功能不可用记忆

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

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

  • 用于数据持久性的可选磁盘支持操作。

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

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

  • 支持可变长度数据类型(包括BLOBandTEXT) not supported byMEMORY.

# Partitioning

MEMORYtables cannot be partitioned.

# Performance Characteristics

MEMORYperformance is constrained by contention resulting from single-thread execution and table lock overhead when processing updates. This limits scalability when load increases, particularly for statement mixes that include writes.

Despite the in-memory processing forMEMORYtables, they are not necessarily faster thanInnoDBtables on a busy server, for general-purpose queries, or under a read/write workload. In particular, the table locking involved with performing updates can slow down concurrent usage ofMEMORYtables from multiple sessions.

Depending on the kinds of queries performed on aMEMORYtable, you might create indexes as either the default hash data structure (for looking up single values based on a unique key), or a general-purpose B-tree data structure (for all kinds of queries involving equality, inequality, or range operators such as less than or greater than). The following sections illustrate the syntax for creating both kinds of indexes. A common performance issue is using the default hash indexes in workloads where B-tree indexes are more efficient.

# Characteristics of MEMORY Tables

TheMEMORYstorage engine does not create any files on disk. The table definition is stored in the MySQL data dictionary.

MEMORYtables have the following characteristics:

  • 空间记忆表被分配在小块中。表对插入使用 100% 动态散列。不需要溢出区域或额外的键空间。空闲列表不需要额外的空间。删除的行被放在一个链表中,并在您向表中插入新数据时重复使用。记忆表也​​没有通常与哈希表中的删除和插入相关的问题。

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

  • 记忆表不能包含斑点要么文本列。

  • 记忆包括支持自动递增列。

  • 非-暂时的 记忆表在所有客户端之间共享,就像任何其他非暂时的桌子。

# MEMORY 表的 DDL 操作

创建一个记忆表,指定子句引擎=内存创建表陈述。

CREATE TABLE t (i INT) ENGINE = MEMORY;

如引擎名称所示,记忆表存储在内存中。它们默认使用哈希索引,这使得它们对于单值查找非常快,并且对于创建临时表非常有用。但是,当服务器关闭时,所有存储在记忆表丢失。表本身继续存在,因为它们的定义存储在 MySQL 数据字典中,但在服务器重新启动时它们是空的。

此示例展示了如何创建、使用和删除记忆桌子:

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;

最大尺寸记忆表是由max_heap_table_size系统变量,默认值为 16MB。强制执行不同的大小限制记忆表,更改此变量的值。有效值创建表,或随后的更改表要么截断表, 是用于表生命周期的值。服务器重新启动还会设置现有的最大大小记忆表到全球max_heap_table_size价值。您可以设置单个表格的大小,如本节后面所述。

# 索引

记忆存储引擎同时支持哈希BTREE索引。您可以通过添加一个给定索引指定一个或另一个使用子句如下所示:

CREATE TABLE lookup
    (id INT, INDEX USING HASH (id))
    ENGINE = MEMORY;
CREATE TABLE lookup
    (id INT, INDEX USING BTREE (id))
    ENGINE = MEMORY;

有关 B 树和哈希索引的一般特征,请参阅第 8.3.1 节,“MySQL 如何使用索引”.

记忆每个表最多可以有 64 个索引,每个索引 16 列,最大键长度为 3072 字节。

如果一个记忆表哈希索引具有高度的键重复(许多索引条目包含相同的值),对影响键值的表的更新和所有删除都明显变慢。这种放缓的程度与重复程度成正比(或与索引基数成反比)。你可以使用一个BTREE索引来避免这个问题。

记忆表可以有非唯一键。(对于哈希索引的实现来说,这是一个不常见的特性。)

被索引的列可以包含空值价值观。

# 用户创建的临时表

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

# 加载数据中

填充一个记忆MySQL 服务器启动时的表,您可以使用初始化文件系统变量。例如,您可以将语句如插入...选择要么加载数据到文件中以从持久数据源加载表,并使用初始化文件命名文件。看第 5.1.8 节,“服务器系统变量”, 和第 13.2.7 节,“加载数据语句”.

# 内存表和复制

当复制源服务器关闭并重新启动时,其记忆表变空。要将这种效果复制到副本,源第一次使用给定的记忆表启动后,它会记录一个事件,通知副本必须通过写入一个表来清空表删除或(来自 MySQL 8.0.22)截断表将该表的语句写入二进制日志。当副本服务器关闭并重新启动时,它的记忆表也​​变空了,它写了一个删除或(来自 MySQL 8.0.22)截断表声明到它自己的二进制日志,它被传递到任何下游副本。

当你使用记忆复制拓扑中的表,在某些情况下,源上的表和副本上的表可能不同。有关处理每种情况以防止过时读取或错误的信息,请参阅第 17.5.1.21 节,“复制和内存表”.

# 管理内存使用

服务器需要足够的内存来维护所有记忆同时使用的表。

如果您从记忆桌子。只有当整个表被删除时才会回收内存。以前用于删除行的内存将重新用于同一表中的新行。释放所有使用的内存记忆当您不再需要表的内容时,执行删除要么截断表删除所有行,或使用完全删除表删除表.要释放已删除行使用的内存,请使用更改表引擎=内存强制重建表。

一行中需要的内存记忆使用以下表达式计算表:

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*))

对齐()表示一个舍入因子,以使行长度成为行长度的精确倍数字符指针大小。大小(字符*)在 32 位机器上为 4,在 64 位机器上为 8。

如前所述,max_heap_table_size系统变量设置最大大小的限制记忆表。要控制单个表的最大大小,请在创建每个表之前设置此变量的会话值。(不要改变全局max_heap_table_size值,除非您打算将该值用于记忆所有客户端创建的表。)以下示例创建两个记忆表,最大大小分别为 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服务器重新启动时的值。

您还可以指定一个MAX_ROWS表选项在创建表声明为记忆表以提供有关您计划在其中存储的行数的提示。这不会使表超出max_heap_table_size值,它仍然作为最大表大小的约束。为了能够使用的最大灵活性MAX_ROWS, 放max_heap_table_size至少与您希望每个的值一样高记忆表能够增长。

# 其他资源

一个专门的论坛记忆存储引擎可在https://forums.mysql.com/list.php?92 (opens new window).