MySQL索引是数据库性能优化的核心知识之一。正确理解索引的原理和使用场景,对于编写高效的SQL语句和设计合理的表结构至关重要。本文将系统介绍MySQL索引的相关知识,包括常见的数据结构、不同存储引擎的索引实现方式,以及聚簇索引和非聚簇索引的区别。
索引的本质是一种数据结构,用于快速定位数据,就像书的目录一样,可以帮助我们快速找到需要的内容,而不必逐页翻阅。不同的数据结构适用于不同的场景,常见的有以下几种:
哈希表是一种基于键值对(Key-Value)的数据结构,通过哈希函数将键映射到某个位置,从而快速访问值。
有序数组在等值查询和范围查询场景下都非常高效。
二叉树是经典的数据结构,每个节点的左子节点小于父节点,右子节点大于父节点。
B树和B+树是为了减少磁盘IO而设计的多路平衡搜索树。
将数据从磁盘读入内存涉及随机IO的访问,是数据库里面成本最高的操作之一。

主键索引(聚簇索引):对应B+树结构示意图如上。 B+树是多层的,B+树每一层中的页都会形成一个双向链表。只有叶子节点存储数据,非叶子节点存储索引值(主键)+指针。
二级索引(非聚簇索引):结构和主键索引类似,只是叶子节点存储的不是完整行数据,而是索引键 + 主键ID
为什么说磁盘IO次数通常在1-3次?
原因:通常来说B+数索引中第一层数据块常驻内存中,第二层其实也极有可能存在内存中,而一个表数10亿数据通常来说也只有4层树高。(下列数据量化)
假设我们使用bigint作为主键类型(8字节),指针占用6字节,InnoDB页大小为16KB,那么:
每个非叶子节点可存储的键值对数量 = 页大小 / (键大小 + 指针大小) = 16384 / (8 + 6) ≈ 1170
假设每条记录大小约为1KB,那么:
这意味着即使存储数十亿条记录,B+树也只需要3-4次磁盘IO即可找到所需数据,效率极高。
下表总结了常见数据结构的优缺点:
| 数据结构 | 等值查询 | 范围查询 | 插入效率 | 适用场景 |
|---|---|---|---|---|
| 哈希表 | ○ | × | ○ | 等值查询 |
| 有序数组 | ○ | ○ | × | 静态数据 |
| 二叉树 | ○ | ○ | ○ | 内存数据 |
| B树 | ○ | ○ | ○ | 磁盘存储 |
| B+树 | ○ | ○ | ○ | 数据库索引 |
MySQL支持多种索引类型,不同存储引擎对索引的支持也有所不同。
BTree索引是MySQL中最常用的索引类型,基于B+树实现。适用于全值匹配、范围查询和排序操作。
哈希索引基于哈希表实现,适用于等值查询,但不支持范围查询和排序。Memory存储引擎默认支持哈希索引。
全文索引用于文本内容的模糊搜索和分词查询,适用于CHAR、VARCHAR和TEXT类型的列。InnoDB和MyISAM支持全文索引。
空间索引用于地理数据查询,支持几何数据类型,但使用较少,通常由专用搜索引擎(如ElasticSearch)代替。
| 索引类型 | InnoDB | MyISAM | Memory |
|---|---|---|---|
| BTree索引 | 支持 | 支持 | 支持 |
| 哈希索引 | 不支持 | 不支持 | 支持 |
| 全文索引 | 支持(≥5.6) | 支持 | 不支持 |
| 空间索引 | 支持 | 支持 | 不支持 |
聚簇索引是一种将数据存储与索引结合的方式,索引的叶子节点直接存储行数据。
InnoDB中,主键索引就是聚簇索引。如果没有定义主键,InnoDB会选择一个唯一的非空索引代替,如果没有这样的索引,会隐式定义一个主键作为聚簇索引。
非聚簇索引的叶子节点存储的是主键值(InnoDB)或数据行指针(MyISAM),而不是行数据本身。查询时需要根据主键值再次查询聚簇索引,这个过程称为回表。
重要设计原则:主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。这就是为什么推荐使用自增整型作为主键,而不是较长的字符串。
回表是指通过非聚簇索引查询时,首先在非聚簇索引树中查找主键值,然后再到聚簇索引树中根据主键值获取行数据的过程。例如:
SELECT * FROM T WHERE k = 5;
如果k字段上有非聚簇索引,查询过程如下:
索引在提供查询加速的同时,也需要维护成本。当对表中的数据进行增加、删除、修改操作时,数据库需要同步更新相关的索引结构,以保持数据一致性。
B+树为了保持平衡,在数据修改时可能需要分裂或合并节点:
因此,索引不是越多越好,需要权衡查询性能和维护成本。对于写多读少的场景,应谨慎添加索引。(通常单表不超过5个为最佳)
尽管MyISAM和InnoDB都使用B+树作为索引结构,但它们的实现方式有本质区别:
MyISAM:
InnoDB:
关键区别:InnoDB是"索引即数据",主键索引的叶子节点就是数据行;而MyISAM是"索引+数据",索引和数据分离存储,通过指针关联。
本文介绍了MySQL索引的常见数据结构、不同类型的索引及其适用场景,以及聚簇索引和非聚簇索引的区别。理解这些基础知识有助于在实际工作中更好地设计表结构和优化查询性能。
索引的出现是为了提高数据查询效率,就像书的目录一样,可以帮助我们快速定位到需要的内容。InnoDB选择B+树作为索引模型,主要是为了减少磁盘IO次数,提高查询效率。通过量化分析可以看出,即使是海量数据,B+树也能在极少的磁盘IO次数内完成查询。
聚簇索引通过将数据存储与索引结合,避免了回表操作,但插入和更新操作可能带来页分裂的问题。非聚簇索引虽然需要回表,但占用空间小,适用于多索引场景。需要注意的是,主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小,这也是推荐使用自增整型作为主键的重要原因。
MyISAM和InnoDB虽然都使用B+树结构,但实现方式不同:InnoDB采用"索引即数据"的聚簇索引设计,而MyISAM使用"索引+数据"的分离式设计。这一根本区别导致了两者在性能特性上的差异。
在实际应用中,建议根据查询需求和数据特性选择合适的索引类型,并尽量避免回表操作,以提高查询性能。同时需要注意索引维护带来的开销,在读写性能之间找到平衡点。
登录查看全部
参与评论
手机查看
返回顶部