前言

我们这里来看一下 MEMORY 存储引擎, 我们常见的那些 临时表什么的, 都是基于 MEMORY

在之前 我们也曾经调试过 相关内存临时表的信息

它主要是 使用 hp_scan, hp_find_record 等等 api 来操作内存中的信息 

我们这里基于 information_schema.TABLES 这张基于 MEMORY 的表来调试 

 

information_schema.TABLES 的创建语句如下 

CREATE TEMPORARY TABLE `TABLES` (
  `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
  `TABLE_TYPE` varchar(64) NOT NULL DEFAULT '',
  `ENGINE` varchar(64) DEFAULT NULL,
  `VERSION` bigint(21) unsigned DEFAULT NULL,
  `ROW_FORMAT` varchar(10) DEFAULT NULL,
  `TABLE_ROWS` bigint(21) unsigned DEFAULT NULL,
  `AVG_ROW_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `DATA_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `MAX_DATA_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `INDEX_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `DATA_FREE` bigint(21) unsigned DEFAULT NULL,
  `AUTO_INCREMENT` bigint(21) unsigned DEFAULT NULL,
  `CREATE_TIME` datetime DEFAULT NULL,
  `UPDATE_TIME` datetime DEFAULT NULL,
  `CHECK_TIME` datetime DEFAULT NULL,
  `TABLE_COLLATION` varchar(32) DEFAULT NULL,
  `CHECKSUM` bigint(21) unsigned DEFAULT NULL,
  `CREATE_OPTIONS` varchar(255) DEFAULT NULL,
  `TABLE_COMMENT` varchar(2048) NOT NULL DEFAULT ''
) ENGINE=MEMORY DEFAULT CHARSET=utf8
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.

 

 

基于 MEMORY 的数据表的空间占用 

表格如下, 这是基于 运行时调试 拿到的数据

对于 varchar 部分字段, 预留了足够的空间, 长度 + 存储的空间, 这里是基于 utf8 编码, 因此存储长度 “1538 = 2 + (512 * 3)”, “193 = 1 + (3 * 64)”

对于 bigint 部分字段, mysql 内部是将其转换为 longlong 存储, 占用 8 字节 

对于 datetime 部分字段, mysql 内部是将其转换为 longlong 存储, 占用 8 字节, 但是这里实际上 仅仅占用了5字节, 应该是有一些 暂时没有看到的机制

最后还有一部分 mysql 的隐藏字段, 比如 hash_field, group_null_fields, null_pack_fields 等等 

这里仅仅只有 null_pack_fields, 占用 3 字节, 最终一条记录合计 9441 字节

58 mysql 存储引擎之 MEMORY_engine

 

TABLES 的各个 业务字段 的创建, 以及记录的计算 

58 mysql 存储引擎之 MEMORY_storage_02

加上 一部分 mysql 的隐藏字段, 比如 hash_field, group_null_fields, null_pack_fields 等等, 这里只有 null_pack 占用的空间, 三字节, 最终 reclength 为 9441

58 mysql 存储引擎之 MEMORY_memory_03

 

基于 MEMORY 的数据表的数据填充 

填充是查询的时候 从内存中的相关数据结构中采集数据, 然后填充到目标 内存表 

58 mysql 存储引擎之 MEMORY_engine_04

 

一级遍历的是可以访问的各个数据库 

58 mysql 存储引擎之 MEMORY_engine_05

一级遍历的是可以访问的各个数据库下面的 所有可以访问的数据表

58 mysql 存储引擎之 MEMORY_engine_06

 

这里是对于 指定的数据表, 填充 TABLES 的各个列的相关数据 

58 mysql 存储引擎之 MEMORY_mysql_07

然后将数据写到 MEMORY 中 

对于有 keyDef 内存表, 会记录 key -> position, 这里 TABLES 没有 keyDef, 仅仅是插入了数据 

58 mysql 存储引擎之 MEMORY_数据_08

 

 

基于 MEMORY 的数据表的数据输出 

对于这里 TABLES 数据表, 是查询该内存表中存放的所有记录 加上过滤条件

但是 在填充数据表的时候, 也已经做了 查询所需要的过滤

假设执行 “select * from `TABLES` where TABLE_NAME = 'tz_test_03';”

从这里可以看出 实际上这个逻辑过滤的条件还是在过滤

58 mysql 存储引擎之 MEMORY_engine_09

 

这里的 partial_cond 为查询条件, 这里是有过滤的 

58 mysql 存储引擎之 MEMORY_mysql_10

 

 

完