底层数据结构
MySQL底层数据结构是采用B+树,与B树的区别在于:
- B+树只有叶子节点存放key和data,其他非叶子节点都只存key;而B树的所有节点都存放key和data
- B+树的叶子节点间有一个双向链表指引,叶子节点内有一条单链表指引;而B树的叶子节点是独立的
- B+树的范围查找只需要遍历链表;而B树需要中序遍历得到结果
聚簇索引与非聚簇索引
聚簇索引:简单来说就是叶子节点保存了key(主键)和data,其中的data保存了所有的数据信息。这也就是为什么InnoDB中“索引即数据,数据即索引”
优点:
- 数据访问更快 ,因为聚簇索引将索引和数据保存在同一个B+树中,因此从聚簇索引中获取数据比非聚簇索引更快
- 聚簇索引对于主键的 排序查找 和 范围查找 速度非常快
- 按照聚簇索引排列顺序,查询显示一定范围数据的时候,由于数据都是紧密相连,数据库不用从多个数据块中提取数据,所以 节省了大量的io操作 。
缺点:
- 插入速度严重依赖于插入顺序 ,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
- 更新主键的代价很高 ,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新
- 二级索引访问需要两次索引查找 ,第一次找到主键值,第二次根据主键值找到行数据
非聚簇索引:又叫二级索引、辅助索引。这里的key是非主键,这里的data通常保存的都是主键的地址值,因此在查询时需要进行回表操作,再走一遍主键索引。
一个库中,只能有一个聚簇索引,可以有多个非聚簇索引(也可以没有)
MyISAM 与 InnoDB对比
MyISAM
的索引方式都是
“
非聚簇
”
的,与
InnoDB
包含
1
个聚簇索引是不同的。小结两种引擎中索引的区
别:
① 在
InnoDB
存储引擎中,我们只需要根据主键值对
聚簇索引
进行一次查找就能找到对应的记录,而在
MyISAM
中却需要进行一次
回表
操作,意味着
MyISAM
中建立的索引相当于全部都是
二级索引
。
②
InnoDB
的数据文件本身就是索引文件,而
MyISAM
索引文件和数据文件是
分离的
,索引文件仅保存数据记录的地址。
③
InnoDB
的非聚簇索引
data
域存储相应记录
主键的值
,而
MyISAM
索引记录的是
地址
。换句话说,InnoDB的所有非聚簇索引都引用主键作为
data
域。
④
MyISAM
的回表操作是十分
快速
的,因为是拿着地址偏移量直接到文件中取数据的,反观
InnoDB
是通过获取主键之后再去聚簇索引里找记录,虽然说也不慢,但还是比不上直接用地址去访问。
⑤
InnoDB
要求表
必须有主键
(
MyISAM
可以没有
)。如果没有显式指定,则
MySQL
系统会自动选择一个可以非空且唯一标识数据记录的列作为主键。如果不存在这种列,则MySQL
自动为
InnoDB
表生成一个隐含字段作为主键,这个字段长度为6个字节,类型为长整型。
索引类型总结
按照数据结构维度划分:
- BTree 索引:MySQL 里默认和最常用的索引类型。只有叶子节点存储 value,非叶子节点只有指针和 key。存储引擎 MyISAM 和 InnoDB 实现 BTree 索引都是使用 B+Tree,但二者实现方式不一样(前面已经介绍了)。
- 哈希索引:类似键值对的形式,一次即可定位。
- RTree 索引:一般不会使用,仅支持 geometry 数据类型,优势在于范围查找,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
- 全文索引:对文本的内容进行分词,进行搜索。目前只有
CHAR
、VARCHAR
,TEXT
列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
按照底层存储方式角度划分:
- 聚簇索引(聚集索引):索引结构和数据一起存放的索引,InnoDB 中的主键索引就属于聚簇索引。
- 非聚簇索引(非聚集索引):索引结构和数据分开存放的索引,二级索引(辅助索引)就属于非聚簇索引。MySQL 的 MyISAM 引擎,不管主键还是非主键,使用的都是非聚簇索引。
按照应用维度划分:
- 主键索引:加速查询 + 列值唯一(不可以有 NULL)+ 表中只有一个。
- 普通索引:仅加速查询。
- 唯一索引:加速查询 + 列值唯一(可以有 NULL)。
- 覆盖索引:一个索引包含(或者说覆盖)所有需要查询的字段的值。
- 联合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。
- 全文索引:对文本的内容进行分词,进行搜索。目前只有
CHAR
、VARCHAR
,TEXT
列上可以创建全文索引。一般不会使用,效率较低,通常使用搜索引擎如 ElasticSearch 代替。
MySQL 8.x 中实现的索引新特性:
- 隐藏索引:也称为不可见索引,不会被优化器使用,但是仍然需要维护,通常会软删除和灰度发布的场景中使用。主键不能设置为隐藏(包括显式设置或隐式设置)。
- 降序索引:之前的版本就支持通过 desc 来指定索引为降序,但实际上创建的仍然是常规的升序索引。直到 MySQL 8.x 版本才开始真正支持降序索引。另外,在 MySQL 8.x 版本中,不再对 GROUP BY 语句进行隐式排序。
- 函数索引:从 MySQL 8.0.13 版本开始支持在索引中使用函数或者表达式的值,也就是在索引中可以包含函数或者表达式。
其他索引优化请移步索引带来的SQL优化_YuuuZh。的博客-CSDN博客
谢谢诸君!
参考:
MySQL索引详解 | JavaGuide(Java面试 + 学习指南)