初识MySQL Memory存储引擎
2016-10-03 22:20:32 阿炯

本站赞助商链接,请多关照。 Memory存储引擎将表的数据存放在内存中,这样访问速度上是其它引擎无法比拟的,尤其是锁表这个问题上。Memory替代以前的Heap成为首选项,但同时向下兼容,Heap仍被支持。

Memory存储引擎特性:


参考如下Memory引擎的使用场景及特点:

能像会话或缓存一样方便操作和管理。
充分发挥内存引擎的特点:高速度、低延迟。
只读或读为主的访问模式(不适合频繁写)。

但是内存表的性能受制于单线程的执行效率和写操作时的表锁开销,这就限制了内存表高负载时的扩展性,特别是混合写操作的并发处理。此外,内存表中的数据在服务器重启后会丢失。

每个Memory表有一个磁盘文件,文件名由表的名字开始,并且由一个'frm'的扩展名来指明它存储的表定义。要明确指出你想要一个Memory表,可使用ENGINE选项来指定:

CREATE TABLE freeoa (i INT) ENGINE = MEMORY;

如它们名字所指明的,Memory表被存储在内存中,且默认使用哈希索引。这使得它们非常快,并且对创建临时表非常有用。可当服务器关闭之时,所有存储在Memory表里的数据被丢失。因为表的定义被存在磁盘上的.frm文件中,所以表自身继续存在,在服务器重启动时它们是空的。


MEMORY表有下列特点:

给Memory表的空间被以小块来分配。表对插入使用100%动态哈希来,不需要溢出区或额外键空间,自由列表无额外的空间需求。已删除的行被放在一个以链接的列表里,并且在你往表里插入新数据之时被重新使用。Memory表也没有通常与在哈希表中删除加插入相关的问题

MEMORY表可以有多达每个表64个索引,每个索引16列,以及3072字节的最大键长度

MEMORY存储引擎支持HASH和BTREE索引
    
如果一个MEMORY 表的哈希索引键高度重复(许多索引条目包含相同的值),与索引键相关的更新以及所有的删除将会明显变慢。重复度与速度成正比,此时你可以使用BTREE 索引来避免这个问题

MEMORY表能够使用非唯一键,支持哈希索引

对可包含NULL值的列的索引

MEMORY表使用固定的记录长度格式,像VARCHAR这样的可变长度类型将转换为固定长度类型在MEMORY表中存储。

MEMORY不能包含BLOB或TEXT列

MEMORY支持AUTO_INCREMENT列

MEMORY表支持INSERT DELAYED

非临时的MEMORY表在所有客户端之间共享,就像其它任何非临时表

MEMORY表内容存储在内存中,它会作为动态查询队列创建内部临时表的共享介质,但是两个类型表的不同在于MEMORY表不会遇到存储转换,而内部表则会:
1、MEMORY表不会转换为磁盘表,而内部临时表如果太大会自动转换为磁盘表。

2、MEMORY表最大值受系统变量 max_heap_table_size 限制,默认为16MB,要改变MEMORY表大小限制,需要改变max_heap_table_size 的值。该值在 CREATE TABLE 时生效并伴随表的生命周期,(当你使用 ALTER TABLE 或 TRUNCATE TABLE命令时,表的最大限制将改变,或重启MYSQL服务时, 所有已存在的MEMORY表的最大限制将使用max_heap_table_size 的值重置。)

服务器需要足够内存来维持所有在同一时间使用的MEMORY表

如果删除行,内存表不会回收内存,只有整张表全部删除的时候,才进行内存回收。同时只有在同一张表中插入新行时才会使用之前删除行的内存空间。要释放已删除行所占用的内存空间,可以使用ALTER TABLE ENGINE=MEMORY对表进行强制重建。当内容过期要释放整张内存表,可以执行DELETE 或 TRUNCATE TABLE清除所有行,或者使用DROP TABLE删除表

当MySQL服务器启动时,如果你想填充MEMORY表,你可以使用--init-file选项。例如,你可以把INSERT INTO ... SELECT 或LOAD DATA INFILE这样的语句放入这个文件中以便从持久稳固的的数据源装载表

如果你正使用复制,当主服务器被关闭且重启动之时,主服务器的MEMORY表变空。可是从服务器意识不到这些表已经变空,所以如果你从它们选择数据,它就返回过时的内容。自从服务器启动后,当一个MEMORY表在主服务器上第一次被使用之时,一个DELETE FROM语句被自动写进主服务器的二进制日志,因此再次让从服务器与主服务器同步。注意,即使使用这个策略,在主服务器的重启和它第一次使用该表之间的间隔中,从服务器仍旧在表中有过时数据。可是如果使用--init-file选项于主服务器启动之时在其上推行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()代表round-up因子,它使得行的长度为char指针大小的确切倍数。sizeof(char*)在32位机器上是4,在64位机器上是8

如前所述,系统变量 max_heap_table_size 用于设置内存表的大小上限。要控制单个表的最大值,需要在创建表之前设置会话变量。(不要设置全局max_heap_table_size 的值,除非你打算所有客户端创建的内存表都使用这个值)

如果服务重启,两张表的大小限制会使用全局的max_heap_table_size值复原。

你也可以通过CREATE TABLE 的MAX_ROWS选项设置表的最大行数,但max_heap_table_size的优先级高于MAX_ROWS,当两者同时存在时为了最大兼容,你需要将max_heap_table_size设置一个合理值。

官方文档:

The maximum size of MEMORY tables is limited by the max_heap_table_size system variable, which has a default value of 16MB. To enforce different size limits for MEMORY tables, change the value of this variable


服务器配置,在配置文件/etc/my.cnf中添加或修改:
[mysqld]
tmp_table_size=2G
max_heap_table_size=2G

修改好这两个参数,要立即生效的话需要重启Mysql服务,或者用超级用户在终端中修改(这样不用重启):
SET GLOBAL tmp_table_size = 1024 * 1024 * 1024 * 2;
SET GLOBAL max_heap_table_size = 1024 * 1024 * 1024 * 2;

查看这些参数:
SELECT @@max_heap_table_size;
or
SHOW VARIABLES LIKE 'max_heap_table_size';
SHOW VARIABLES LIKE '%table_size';

tmp_table_参数与heap_table_在本质上基本一致,它用于指定临时表的大小。

参考来源:

MySQL Memory 存储引擎浅析

15.4 The MEMORY Storage Engine