参考来源:康师傅:https://www.bilibili.com/video/BV1iq4y1u7vj?p=119
爱编程的大李子:https://blog.csdn.net/LXYDSF/article/details/125873790
一、MyISAM 索引的原理
MyISAM 引擎使用 B+Tree 作为索引结构,叶子节点的 data 域存放的是 数据记录的地址 (所以MyISAM把索引和数据分开存储了)
我们知道InnoDB中索引即数据,也就是聚簇索引的那棵B+树的叶子节点中已经把所有完整的用户记录都包含了,而MyISAM的索引方案虽然也使用树形结构,但是却将索引和数据分开存储: .
- 将表中的记录按照记录的插入顺序单独存储在一个文件中,称之为数据文件。这个文件并不划分为若干个数据页,有多少记录就往这个文件中塞多少记录就成了。由于在插入数据的时候并没有刻意按照主键大小排序,所以我们并不能在这些数据上使用二分法进行查找。
- 使用MyISAM存储引擎的表会把索引信息另外存储到一个称为索引文件的另一个文件中。MyISAM 会单独为表的主键创建一个索引, 只不过在索引的叶子节点中存储的不是完整的用户记录,而是主键值+数据记录地址的组合。
二、MyISAM 与 InnoDB 对比
MyISAM 的索引方式都是“非聚簇”的,与 InnoDB 包含 1 个聚簇索引是不同的
两种引擎中索引的区别:
- 在 InnoDB 存储引擎中,我们只需要根据主键值对 聚簇索引 进行一次查找就能找到对应的记录,而在 MyISAM 中却需要进行一次 回表 操作,意味着 MyISAM 中建立的索引相当于全部都是 二级索引 。(MyISAM的回表就是根据地址到data表中查找数据)
- InnoDB 的数据文件本身就是索引文件,而 MyISAM 索引文件和数据文件是 分离的 ,索引文件仅保存数据记录的地址。
- InnoDB 的非聚簇索引 data 域存储相应记录 主键的值 ,而 MyISAM 索引记录的是 地址 。换句话说, InnoDB 的所有非聚簇索引都引用主键作为 data 域
- MyISAM 的回表操作是十分 快速 的,因为是拿着地址偏移量直接到文件中取数据的,反观 InnoDB 是通过获取主键之后再去聚簇索引里找记录,虽然说也不慢,但还是比不上直接用地址去访问。
InnoDB 要求表 必须有主键 ( MyISAM 可以没有 )。如果没有显式指定,则 MySQL 系统会自动选择一个可以非空且唯一标识数据记录的列作为主键。如果不存在这种列,则 MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,这个字段长度为 6 个字节,类型为长整型
- InnoDB的主键是为了生成聚簇索引,所以必须有;MyISAM 中的索引都是非聚簇的,数据和索引分离,所以对MyISAM没有要求。但是为了查询方便,还是建议指定某一字段为主键,从而方便存储引擎为其构建索引,提升查询效率。
建议:
- InnoDB不建议使用过长的字段作为主键,因为所有二级索引都引用主键索引,过长的主键索引会令二级索引变得过大。
- 建议使用单调递增的字段作为InnoDB的主键,因为InnoDB数据文件本身是一棵B+Tree, 非单调的主键会造成在插入新记录时,数据文件为了维持B+ Tree的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。