在mysql中索引类型包括这几种B + Tree索引、hash索引、全文索引、空间索引。其中B+Tree索引是默认索引类型。且B + Tree(平衡树)索引大致分为两类 聚簇索引 和非聚簇索引(指MyISM的非聚簇索引)。
a. 聚簇索引是一种索引方式,InnoDB引擎要求必须有聚簇索引。索引采用B + Tree索引结构实现。聚簇索引是按照表主键顺序构建一个B+Tree结构。其叶子节点存储了是行数据(包含主键值)。
b. 叶子节点中行数据和主键值紧凑的存储在一起,按照主键顺序存储整张表的数据,占用的空间就是整张表的大小。
c. 聚簇索引是通过主键聚集数据,若定义了主键,则主键索引就为聚簇索引。若没定义主键,则表中第一个非空唯一的列作为聚簇索引。都不满足时,InnoDB会建一个隐藏列row-id作为聚簇索引。所以InnoDB引擎的表要求必须有聚簇索引(主键索引)。
d. 二级索引(辅助索引或非主键索引)是在聚簇索引之上创建。是根据索引列 构建的 B+Tree结构,在其叶子节点只存储索引列对应的数据值和主键值。二级索引占用的空间比聚簇索引小很多,通常创建二级索引就是为了提高查询效率。一个InnoDB表只能创建一个聚簇索引,可以创建多个二级索引。当索引覆盖扫描时可以直接从B+Tree中获取这些值,不会通过主键查询主键索引(回表查询)获取数据。
优点
a. 支持范围查询:聚簇索引是按照主键顺序存储的,因此天然支持范围查询。当查询条件包含主键或主键一部分时,数据库利用聚簇索引快速定位到满足条件的数据范围。
b. 查询速度快:聚簇索引决定了数据在磁盘上的物理顺序,使得相关数据在物理上紧凑地存储在一起。数据库可以通过较小的I/O操作读取所需数据。且索引的叶子节点包含了数据行的完整数据,索引覆盖扫描时,可以从二级索引 直接获取索引列的值减少二次查询主键索引(所谓回表查询减少磁盘I/O操作),加快查询速度。
c. 存储效率高:聚簇索引包含了行数据,避免了在非聚簇索引中存储主键所需的空间。此外,当表中数据删除或修改时,能更有效的管理和回收磁盘空间,减少空间浪费。
缺点
a. 插入速度慢:聚簇索引的插入严重依赖于插入顺序。按主键顺序插入数据是加载数据页到InnoDB表中速度最快的方式。若插入数据的顺序与主键顺序不一致,可能会出现页分裂(page split)现象,这会降低插入性能,并导致表占用更多的磁盘空间。
解决方案:建议定义一个自增的ID列作为主键,以确保数据按照顺序插入。
b. 更新主键代价大:更新聚簇索引中的主键会导致数据行的移动。因为InnoDB将索引和数据保存在同一个B+Tree中,所以更新主键值需移动数据行到新位置,且可能触发页分裂或页合并,这会降低性能。
解决方案:建议主键列设置为不可更新,或尽量避免更新主键值。
c. 二级索引访问需两次查询:由于二级索引叶子节点只存储了索引列值和主键值,当获取非索引列的数据时,需先找到索引上主键值,再通过主键值去聚簇索引上找行数据,这样需要两次索引查询,降低了访问效率。
解决方案:经常通过二级索引获取非索引列的数据时,可以考虑包括在主键中或作为索引覆盖的一部分,以减少访问数据时的开销。
d. 表结构修改可能更复杂:因聚簇索引将索引和数据紧凑在一起,因此对表结构修改(如添加、删除列或更改列数据类型)可能会更加复杂和耗时。这个操作可能需重建聚簇索引,从而影响数据库的性能和可用性。
解决方案:在修改表结构之前,应仔细评估其对数据库性能的影响,并尽可能在数据库负载较低的时间段操作。
这里介绍的非聚簇索引是指MyISM引擎中的非聚簇索引,不是InnoDB引擎中的非聚簇索引(二级索引结构也为非聚簇索引结构)。
a. 非聚簇索引是一种索引方式,MyISM采用的是非聚簇索引,其索引文件结构为B+Tree结构。索引文件和数据文件是分离的。索引文件存储B+Tree结构,数据文件存储表中的数据行。
b. 索引文件是按照索引键值和表数据内存地址构建的B+Tree,其结构的叶子节点存储了索引列的值和指向数据文件中记录的物理位置(通常磁盘地址)的指针。
c. 每个索引对应一个B+Tree结构的索引文件,索引文件是独立的。通过辅助索引检索时,无需访问主键索引树。
d. 执行查询时,会利用非聚簇索引中的索引列值对B+Tree从根节点逐层查找,找到叶子节点。从叶子节点中获取记录的物理位置(磁盘地址)找到数据文件,从数据文件中获取响应的记录。当索引覆盖扫描时,可以直接从索引文件中返回这些值,无需再访问数据文件。
优点
a. 索引灵活性高:每个表可以创建多个非聚簇索引,每个索引都可以基于不同列组合,增加了索引的灵活性。能够更好的支持查询需求,提高查询效率。
b. 更新代价少:因非聚簇索引叶子节点不存储行数据,存放了数据行本身的物理位置(磁盘地址)。在修改时不需想聚簇索引那样重新排序或移动数据,减少了数据修改的开销。
c. 支持覆盖查询:若查询只访问索引列数据,可以直接通过索引文件返回这些值,无需访问数据文件,可以减少二次查询,显著提高查询效率。
缺点
a. 范围查询效率低:在范围查询时,因索引是无序的,需按照索引文件和数据文件内存一个个检索,从而降低了查询效率。
b. 更新操作效率较差:当对表中数据更新时,需要同时更新索引文件和数据文件,可能会导致性能下降,特别是索引列的值发生变化时,可能需要重新插入索引值,增加了写操作的开销。
c. 查询非索引列性能差:若查询条件不包含索引列或需查询非索引列的数据,需要进行全表扫描,这会显著降低查询性能。
综上所述,聚簇索引在范围查询、存储效率上有明显优势。非聚簇索引在访问速度、索引灵活性以及读多写少的应用场景下更有优势。在实际应用中,需根据具体需求选择合适的存储引擎和索引策略。