首页 > 数据库 > > 15.3 MEMORY 存储引擎
参考官方文档:
https://dev.mysql.com/doc/refman/5.7/en/memory-storage-engine.html
MEMORY存储引擎(以前称为HEAP)创建包含存储在内存中的内容的专用表。 由于数据容易受到崩溃,硬件问题或断电的影响,因此只能将这些表用作临时工作区或从其他表中提取数据的只读缓存。
何时使用MEMORY或NDB群集
希望将MEMORY存储引擎使用在,高可用或频繁更新的数据的应用程序的开发人员应考虑NDB Cluster是否是更好的选择。 MEMORY引擎的典型用例涉及以下特征:
NDB Cluster提供与MEMORY引擎相同的功能,具有更高的性能水平,并提供MEMORY不具备的其他功能:
性能特点
MEMORY性能受到处理更新时单线程执行和表锁开销导致的争用的限制。这会限制负载增加时的可伸缩性,特别是对于包含写的混合语句。
尽管对MEMORY表进行了内存处理,但它们不一定比繁忙服务器上的InnoDB表,通用查询或读/写工作负载更快。特别是,执行更新所涉及的表锁定会减慢来自多个会话的MEMORY表的并发使用。
根据在MEMORY表上执行的查询类型,您可以创建索引作为默认哈希数据结构(用于基于唯一键查找单个值)或通用B树数据结构(适用于所有类型涉及等于,不等式或范围运算符(例如小于或大于)的查询)。以下部分说明了创建这两种索引的语法。常见的性能问题是在工作负载中使用默认哈希索引,但是B树索引更有效。
MEMORY 表的特征
MEMORY存储引擎将每个表与一个磁盘文件相关联,该磁盘文件存储表定义(而不是数据)。 文件名以表名开头,扩展名为.frm。
MEMORY表具有以下特征:
MEMORY 表的 DDL 操作
要创建MEMORY表,请在CREATE TABLE语句中指定ENGINE = MEMORY子句。
CREATE TABLE t (i INT) ENGINE = MEMORY;
如引擎名称所示,MEMORY表存储在内存中。 它们默认使用哈希索引,这使得它们对于单值查找非常快,并且对于创建临时表非常有用。 但是,当服务器关闭时,存储在MEMORY表中的所有行都将丢失。 表本身仍然存在,因为它们的定义存储在磁盘上的.frm文件中,但在服务器重新启动时它们是空的。
此示例显示了如何创建,使用和删除MEMORY表:
CREATE TABLE test ENGINE=MEMORY
SELECT ip,SUM(downloads) AS down
FROM log_table GROUP BY ip;
SELECT COUNT(ip),AVG(down) FROM test;
DROP TABLE test;
MEMORY表的最大大小受max_heap_table_size系统变量的限制,该变量的默认值为16MB。 要对MEMORY表强制执行不同的大小限制,请更改此变量的值。 对CREATE TABLE或后续ALTER TABLE或TRUNCATE TABLE有效的值是用于表的生命周期的值。 服务器重新启动还会将现有MEMORY表的最大大小设置为全局max_heap_table_size值。 您可以设置各个表的大小,如本节后面所述。
索引
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;
MEMORY表每个表最多可包含64个索引,每个索引16列,最大key长度为3072字节。
如果MEMORY表哈希索引具有高度密钥重复(许多索引条目包含相同的值),则对表的影响键值和所有删除的更新会明显变慢。 这种减速程度与重复程度成正比(或与指数基数成反比)。 您可以使用BTREE索引来避免此问题。
MEMORY表可以有非唯一键。 (这是哈希索引实现的一个不常见的功能。)
索引的列可以包含NULL值。
用户创建的和临时表
MEMORY表内容存储在内存中,这是MEMORY表与处理查询时服务器动态创建的内部临时表共享的属性。 但是,这两种类型的表的区别在于MEMORY表不受存储转换的影响,而内部临时表是:
加载数据
要在MySQL服务器启动时填充MEMORY表,可以使用--init-file选项。 例如,您可以将INSERT INTO ... SELECT或LOAD DATA INFILE等语句放入此文件以从持久数据源加载表
内存表和复制
服务器的MEMORY表在关闭并重新启动时变为空。 如果服务器是复制主服务器,则其从属服务器不知道这些表已变为空,因此如果从从属服务器上的表中选择数据,则会看到过时的内容。 要同步主MEMORY表和从属MEMORY表,当主服务器启动后第一次使用MEMORY表时,DELETE语句将写入主服务器的二进制日志,以清空从服务器上的表。 在主服务器重新启动和第一次使用表之间的间隔期间,从服务器仍然在表中过期数据。 要在对从属设备的直接查询可以返回过时数据时避免此间隔,请使用--init-file选项在启动时填充主服务器上的MEMORY表。
管理内存使用
服务器需要足够的内存来维护同时使用的所有MEMORY表。
如果从MEMORY表中删除单个行,则不会回收内存。 仅在删除整个表时才回收内存。 以前用于已删除行的内存将重新用于同一表中的新行。 要在不再需要其内容时释放MEMORY表使用的所有内存,请执行DELETE或TRUNCATE 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表的最大大小限制。 要控制各个表的最大大小,请在创建每个表之前设置此变量的会话值。 (不要更改全局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值。
您还可以在MEMATE表的CREATE TABLE语句中指定MAX_ROWS表选项,以提供有关您计划在其中存储的行数的提示。 这不会使表超出max_heap_table_size值,该值仍然作为最大表大小的约束。 为了最大程度地灵活地使用MAX_ROWS,请将max_heap_table_size设置为至少与您希望每个MEMORY表能够增长的值一样大。
其他资源
有关MEMORY存储引擎的论坛可在http://forums.mysql.com/list.php?92上找到。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69946831/viewspace-3170157/ ,如需转载,请注明出处,否则将追究法律责任。