15.3 MEMORY 存储引擎
MEMORY
存储引擎(以前称为HEAP
)创建特殊用途的 table,其内容存储在内存中。由于数据容易受到崩溃,硬件问题或电源中断的影响,因此只能将这些 table 用作临时工作区或只读缓存,以存储从其他 table 中提取的数据。
table15.4 MEMORY 存储引擎功能
Feature | Support |
---|---|
B-tree indexes | Yes |
备份/时间点恢复 (在服务器中而不是在存储引擎中实现.) | Yes |
集群数据库支持 | No |
Clustered indexes | No |
Compressed data | No |
Data caches | N/A |
Encrypted data | 是(通过加密功能在服务器中实现.) |
外键支持 | No |
全文搜索索引 | No |
地理空间数据类型支持 | No |
地理空间索引支持 | No |
Hash indexes | Yes |
Index caches | N/A |
Locking granularity | Table |
MVCC | No |
复制支持 (在服务器中而不是在存储引擎中实现.) | 受限(请参阅本节后面的讨论.) |
Storage limits | RAM |
T-tree indexes | No |
Transactions | No |
更新数据字典的统计信息 | Yes |
何时使用 MEMORY 或 NDB 群集
希望部署使用MEMORY
存储引擎处理重要,高度可用或经常更新的数据的应用程序的开发人员,应考虑 NDB Cluster 是否是更好的选择。 MEMORY
引擎的典型用例涉及以下 Feature:
-
涉及瞬态,非关键数据的操作,例如会话 Management 或缓存。当 MySQL 服务器停止或重新启动时,
MEMORY
table 中的数据将丢失。 -
内存中存储可实现快速访问和低延迟。数据量可以完全容纳在内存中,而不会导致 os 换出虚拟内存页面。
-
只读或只读的数据访问模式(有限的更新)。
NDB 群集具有与MEMORY
引擎相同的功能,并且具有更高的性能水平,并提供了MEMORY
不可用的其他功能:
-
行级锁定和多线程操作可减少 Client 端之间的争用。
-
即使包含写的语句混合也具有可伸缩性。
-
可选的磁盘支持操作,可确保数据持久性。
-
无共享架构和多主机操作,没有单点故障,可实现 99.999%的可用性。
-
跨节点自动数据分发;应用程序开发人员无需制定自定义分片或分区解决方案。
Performance Characteristics
MEMORY
性能受到单线程执行和处理更新时 table 锁开销所导致的争用的限制。当负载增加时,这会限制可伸缩性,尤其是对于包含写入的语句混合。
尽管对MEMORY
table 进行了内存内处理,但它们不一定要比繁忙服务器上的InnoDBtable,用于通用查询或在读/写工作负载下要快。特别是,执行更新所涉及的 table 锁定会减慢来自多个会话的MEMORY
table 的并发使用。
根据对MEMORY
table 执行的查询的类型,您可以将索引创建为默认哈希数据结构(用于基于唯一键查找单个值)或通用 B 树数据结构(用于各种类型)涉及相等,不相等或范围运算符(例如小于或大于)的查询。以下各节说明了创建两种索引的语法。一个常见的性能问题是在 B 树索引更有效的工作负载中使用默认哈希索引。
MEMORYtable 的 Feature
MEMORY
存储引擎将每个 table 与一个磁盘文件关联,该磁盘文件存储 table 定义(而不是数据)。文件名以 table 名开头,extensions 为.frm
。
MEMORY
table 具有以下 Feature:
-
MEMORY
个 table 的空间以小块分配。table 对插入使用 100%动态哈希。不需要溢出区域或额外的密钥空间。空闲列 table 不需要额外的空间。删除的行放在链接列 table 中,当您在 table 中插入新数据时可以重复使用。MEMORY
table 也没有与哈希 table 中的删除和插入通常相关的问题。 -
MEMORY
table 使用固定长度的行存储格式。可变长度类型(例如VARCHAR)使用固定长度存储。 -
MEMORY
支持AUTO_INCREMENT
列。 -
与所有其他非
TEMPORARY
table 一样,非TEMPORARY
MEMORY
table 在所有 Client 端之间共享。
MEMORYtable 的 DDL 操作
要创建MEMORY
table,请在CREATE TABLE语句上指定子句ENGINE=MEMORY
。
CREATE TABLE t (i INT) ENGINE = MEMORY;
如引擎名称所示,MEMORY
个 table 存储在内存中。默认情况下,它们使用哈希索引,这使它们对于单值查找非常快,对于创建临时 table 非常有用。但是,当服务器关闭时,存储在MEMORY
table 中的所有行都会丢失。这些 table 本身 continue 存在,因为它们的定义存储在磁盘上的.frm
文件中,但是在服务器重新启动时它们为空。
本示例说明了如何创建,使用和删除MEMORY
table:
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
table 的最大大小受max_heap_table_size系统变量的限制,系统变量的默认值为 16MB。要对MEMORY
table 实施不同的大小限制,请更改此变量的值。 CREATE TABLE或后续的ALTER TABLE或TRUNCATE TABLE的有效值是 table 生命周期内使用的值。服务器重新启动还会将现有MEMORY
table 的最大大小设置为全局max_heap_table_size值。您可以按照本节后面的说明设置单个 table 的大小。
Indexes
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 树和哈希索引的一般 Feature,请参见第 8.3.1 节“ MySQL 如何使用索引”。
MEMORY
table 每个 table 最多可以有 64 个索引,每个索引最多可以有 16 列,最大键长为 3072 字节。
如果MEMORY
table 哈希索引具有高度的键重复性(许多索引条目包含相同的值),则影响键值的 table 更新和所有删除操作的速度将显着降低。此减速的程度与重复程度成正比(或与索引基数成反比)。您可以使用BTREE
索引来避免此问题。
MEMORY
table 可以具有非唯一键。 (这是哈希索引实现的罕见功能.)
被索引的列可以包含NULL
个值。
用户创建的临时 table
MEMORY
table 的内容存储在内存中,这是MEMORY
table 与服务器在处理查询时动态创建的内部临时 table 共享的属性。但是,两种类型的 table 的区别在于MEMORY
table 不进行存储转换,而内部临时 table 是:
-
如果内部临时 table 太大,服务器将自动将其转换为磁盘存储,如第 8.4.4 节“ MySQL 中的内部临时 table 使用”中所述。
-
用户创建的
MEMORY
table 永远不会转换为磁盘 table。
Loading Data
要在 MySQL 服务器启动时填充MEMORY
table,可以使用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 内存使用
服务器需要足够的内存来维护所有正在使用的MEMORY
table。
如果从MEMORY
table 中删除单个行,则不会回收内存。仅在删除整个 table 时才回收内存。先前用于已删除行的内存将重新用于同一 table 中的新行。要在不再需要MEMORY
table 的内容时释放其使用的所有内存,请执行DELETE或TRUNCATE TABLE删除所有行,或使用DROP TABLE一起删除该 table。要释放已删除的行使用的内存,请使用ALTER TABLE ENGINE=MEMORY
强制重建 table。
MEMORY
table 中一行所需的内存使用以下 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系统变量设置MEMORY
table 的最大大小的限制。要控制单个 table 的最大大小,请在创建每个 table 之前设置此变量的会话值。 (除非您打算将该值用于所有 Client 端创建的MEMORY
table,否则不要更改全局max_heap_table_size值。)以下示例创建两个MEMORY
table,最大大小分别为 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值。
您还可以在MEMORY
table 的CREATE TABLE语句中指定MAX_ROWS
table 选项,以提示您计划存储在其中的行数。这不能使 table 增长到超过max_heap_table_size值,该值仍然是最大 table 大小的约束。为了最大程度地灵活使用MAX_ROWS
,请将max_heap_table_size至少设置为希望每个MEMORY
table 能够增长到的值。
Additional Resources
https://forums.mysql.com/list.php?92提供了一个专门讨论MEMORY
存储引擎的论坛。