前言
我们这里来看一下 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
基于 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 字节
TABLES 的各个 业务字段 的创建, 以及记录的计算
加上 一部分 mysql 的隐藏字段, 比如 hash_field, group_null_fields, null_pack_fields 等等, 这里只有 null_pack 占用的空间, 三字节, 最终 reclength 为 9441
基于 MEMORY 的数据表的数据填充
填充是查询的时候 从内存中的相关数据结构中采集数据, 然后填充到目标 内存表
一级遍历的是可以访问的各个数据库
一级遍历的是可以访问的各个数据库下面的 所有可以访问的数据表
这里是对于 指定的数据表, 填充 TABLES 的各个列的相关数据
然后将数据写到 MEMORY 中
对于有 keyDef 内存表, 会记录 key -> position, 这里 TABLES 没有 keyDef, 仅仅是插入了数据
基于 MEMORY 的数据表的数据输出
对于这里 TABLES 数据表, 是查询该内存表中存放的所有记录 加上过滤条件
但是 在填充数据表的时候, 也已经做了 查询所需要的过滤
假设执行 “select * from `TABLES` where TABLE_NAME = 'tz_test_03';”
从这里可以看出 实际上这个逻辑过滤的条件还是在过滤
这里的 partial_cond 为查询条件, 这里是有过滤的
完