InnoDB 和 MyISAM 的数据分布是什么样的?
INSERT test(id, num, tag) VALUES(2, 3, 'no.7');
INSERT test(id, num, tag) VALUES(8, 23, 'no.8');
INSERT test(id, num, tag) VALUES(1, 11, 'no.9');
复制代码
[](()MyISAM 的数据存储
MyISAM 按照数据插入的顺序存储在磁盘上,我们假设第一行数据在数据库表文件中的偏移位置是 1,以此类推。 如下图
现在我们验证一下,使用 SELECT * FROM test;
扫描全表(SELECT * 不会使用任何索引,可以用 explain
实际观察下),输出的顺序正是我们 sql 插入的顺序,大家可以调整 sql 的顺序再次插入,观察输出顺序。
搞清楚了 MyISAM 的数据存储方式,再来看下主键索引的存储。我们假设每个磁盘块只能存储两个节点数据,MyISAM 的主键分布如下图:
![](https://img-blog.csdnimg.cn/img_convert/fd4f8d44e2f55575005639acb5cedcca. Java 开源项目【ali1024.coding.net/public/P7/Java/git】 png)
其实 MyISAM 的二级索引和主键索引并无区别,只是名称不同罢了,二级索引 key(num)分布如下图:
二级索引子节点也只存储了索引列(num)和文件的偏移量(P),但可以看出 num 是有序的,这在范围查找(比如:where num > 3
)是非常有利的,但文件的偏移量并没有规律,当需要回表查询其他字段,可能会导致多次随机 I/O。
当对增加数据时 MyISAM 直接添加到文件尾部,不需要移动其他数据,而且更新主键时,也不会导致其他行数据移动,但它不支持行级锁,修改时直接锁表。若不需要事务支持,对读多写少的场景可以考虑 MyISAM 引擎,但不要默认使用 MyISAM 引擎。
[](()InnoDB 的数据存储
InnoDB 支持聚簇索引,所以使用非常不同的方式存储同样的数据。InnoDB 数据存储方式如下图:
注意整个树和 MyISAM 的主键索引非常类似,唯一的区别是叶子节点,InnoDB 的叶子节点存储了整个行数据(id、num、tag
),而不是只有索引。聚簇索引“就是”整个表 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》开源 ,而不像 MyISAM 那样需要单独的行存储文件。当更新主键 id 时,可能会导致数据行移动,因为索引和数据是存储在一起的。若主键 id 是乱序写入的,InnoDB 不得不做页分裂操作时,至少会导致修改三个页(分裂产生的两个页,以及他们的父节点页面),而不是一个页,这和 MyISAM 新增数据时添加到文件尾部很不一样。所以使用 InnoDB 引擎尽可能的按主键顺序插入数据。
InnoDB 的二级索引和聚簇索引也不一样。InnoDB 二级索引的叶子节点中存储的不是行数据的“偏移量”,而是主键值。这意味着通过二级索引查找行数据,存储引擎需要找到二级索引的叶子节点获得对应的主键值,然后根据这个值去聚簇索引中查找到对应的行数据。这里做了重复的工作:两次 B-Tree 查找,而不是一次。这样的策略减少了当出现行移动或者数据页分裂时二级索引的维护工作。二级索引的数据分布如下图:
架构学习资料
由于篇幅限制小编,pdf 文档的详解资料太全面,细节内容实在太多啦,所以只把部分知识点截图出来粗略的介绍,每个小节点里面都有更细化的内容!
评论