聚簇索引与非聚簇索引分别是MySQL不同存储引擎组织索引和数据存储的两种不同方式。按照官方文档的说法,InnoDB里面,除了聚簇索引之外其他都是二级索引,也就是没有非聚簇索引,而MyISAM使用的索引都是非聚簇索引。
- 聚簇索引:将记录和文件一起存放到B+树中的索引中,即B+树的外部叶子节点存放记录,内部节点存放索引。
- 二级索引:InnoDB里面除了聚簇索引之外,都是二级索引,或者说是
聚簇索引的辅助索引 。其对应的B+树叶子节点里面存储的是主键值和相应的索引列。有的人也把二级索引叫非聚簇索引,我认为这是不合理的,因为聚簇的意思是:“把数据和索引聚在一起”。而二级索引的叶子节点也是有数据的,因此,称之为非聚簇索引是不太合适的。不过只要知道背后的原因叫什么都没关系。 - 非聚簇索引:索引和数据分开存储在不同的文件中,B+树叶子节点存放是的记录的地址。
非聚簇索引和二级索引:
- 对于MyISAM来说,我们知道MyISAM的数据和索引文件是分开存储的。MyISAM的数据并没有被划分成若干数据页,而是按照用户的插入数据依次怼到一个文件里面。然后是建立对应的索引。在MyISAM里面全是非聚簇索引,并且非聚簇索引的叶子节点存储的是对应记录在数据文件中的地址。在使用索引进行查找的时候,首先通过B+树找到对应记录所在的地址,然后根据地址,再来一次IO找到真正数据。
- 而在InnoDB里面,索引即数据,数据即索引,也就是数据和索引是一起存储的。它的
二级索引 的叶子节点存储的是主键值和对应的索引列。当我们进行SELECT查找的时候,如果所查的字段被索引列包含,那么直接可以通过二级索引 的叶子节点获取到数据,这叫索引覆盖。而如果所查的字段不能被索引列包含,那么就需要根据叶子节点中存储的主键id,去聚簇索引中再查一次,以获取所需的数据,这叫回表操作。所以我们在使用InnoDB存储引擎的时候,尽量不要使用SELECT * 这样的操作。 - InnoDB的二级索引和MyISAM的非聚簇索引和那个更高效还真不好说。如果做到索引覆盖,无疑是InnoDB更加高效,因为不用回表。但是如果都需要回表,对于InnoDB来说,还需要再查一次聚簇索引的B+树才能获取到对应的数据,而MyISAM回表的时候只需要拿着地址去数据文件中找就可以了。所以在回表的时候,MyISAM更加高效。
mysql官方文档链接:https://dev.mysql.com/doc/refman/5.7/en/innodb-index-types.html
|