Memory引擎适合存临时、可丢、读多写少的热数据,如会话缓存、中间聚合结果、路由映射表;不支持持久化、TEXT/BLOB字段和全文索引,且受max_heap_table_size限制,高并发写入易因表级锁和哈希索引局限导致性能下降。

Memory引擎适合什么场景
它只适合存临时、可丢、读多写少的热数据,比如会话缓存、中间聚合结果、路由映射表。不是所有“要快”的地方都该用 MEMORY——它不持久,服务重启就空了;也不支持 TEXT、BLOB 类型;更没法建全文索引。
常见错误现象:CREATE TABLE ... ENGINE=MEMORY 成功,但插入 TEXT 字段时报错 ERROR 1163 (HY000): The used table type doesn't support BLOB/TEXT columns;或者应用重启后发现“缓存”全没了,还以为是代码漏写持久化逻辑。
使用场景举例:
- 实时统计仪表盘的分钟级汇总(如每分钟 UV、PV 计数器)
- JOIN 大表前先载入的小维度表(比如
country_code映射) - 存储存储过程里临时中间结果,避免反复查磁盘表
创建Memory表必须注意的参数
MEMORY 表本质是内存里的哈希或 B-Tree 结构,但它的行为受全局配置约束,不是建完就自动飞起来。
关键点:
- 最大容量由
max_heap_table_size控制,默认通常只有 16MB,超了会报错ERROR 1114 (HY000): The table 'xxx' is full - 这个变量是会话级的,
SET SESSION max_heap_table_size = 268435456可临时调高,但不能超过全局值max_heap_table_size的上限 - 建表时若指定
AVG_ROW_LENGTH或MAX_ROWS,MySQL 会按AVG_ROW_LENGTH × MAX_ROWS预估大小,并与max_heap_table_size比较,不满足就拒绝创建 - 主键和唯一索引默认用哈希(
HASH),范围查询(<,BETWEEN)效率极差;需要范围扫描就得显式加USING BTREE
示例:
CREATE TABLE session_cache ( sid VARCHAR(128) PRIMARY KEY USING BTREE, user_id INT, last_access TIMESTAMP ) ENGINE=MEMORY AVG_ROW_LENGTH=256 MAX_ROWS=100000;
为什么Memory表有时比InnoDB还慢
不是所有内存操作都快——瓶颈常在锁、争用和索引类型上。
典型问题:
-
MEMORY表用表级锁(LOCK TABLES级别),高并发写入时严重阻塞,而InnoDB是行级锁 - 默认哈希索引只支持等值查询(
=,IN),ORDER BY或LIKE 'abc%'会触发全表扫描 - 没设主键或唯一键时,MySQL 会自动建一个隐式哈希索引,但无法用于排序或分组,
GROUP BY变成内存中软排序,反而更耗 CPU - 如果数据量接近
max_heap_table_size上限,频繁 INSERT/DELETE 会引发内存碎片,性能逐步下滑
替代方案比硬上Memory更靠谱
真要加速,优先考虑更稳的路子:
- 小而热的维度表:用
InnoDB+ 足够大的innodb_buffer_pool_size,让它常驻内存,效果接近MEMORY但不丢数据 - 聚合类中间结果:用
TEMPORARY TABLE(默认就是MEMORY,但生命周期绑定会话,更安全) - 高频键值查询:直接上 Redis,避免 MySQL 解析、权限、网络等额外开销
- 需要事务或崩溃恢复:别碰
MEMORY,它连 crash safe 都不保证
真正容易被忽略的是:你看到的“慢”,往往不是磁盘 IO 慢,而是查询没走索引、统计信息过期、或者连接池打满导致排队——这时候换引擎只是转移问题。










