索引大家都陌生了。包括市面上也有超级多的资料。但是总感觉讲的不够全面。看着很蒙圈。知道这个东西。但是轮到自己说的时候总说不清关系。于是准备总结一下子吧。
# 索引的概念
索引(Index)是帮助MySQL高效获取数据的数据结构。索引最形象的比喻就是图书的目录。注意只有在大量数据中查询时索引才显得有意义。 在MySQL中索引是在存储引擎层实现的,而不是在服务器层实现的,所以不同存储引擎具有不同的索引类型和实现。
常见的索引分类如下:
- 按数据结构分类: B+tree索引、Hash索引、Full-text索引。
- 按物理存储分类: 聚集索引、非聚集索引(也叫二级索引、辅助索引)。
- 按字段特性分类: 主键索引(PRIMARY KEY)、唯一索引(UNIQUE)、普通索引(INDEX)、全文索引(FULLTEXT)。
- 按字段个数分类: 单列索引、联合索引(也叫复合索引、组合索引)。
# 按数据结构分类
MySQL索引按数据结构分类可分为:B+tree索引、Hash索引、Full-text索引。
InnoDB | MyISAM | Memory | |
---|---|---|---|
B+tree索引 | √ | √ | √ |
Hash索引 | × | × | × |
Full-text索引 | √(MySQL5.6.4) | √ | ×| |
InnoDB实际上也支持Hash索引,但是InnoDB中Hash索引属于是自适应Hash索引,它的创建过程由存储引擎引擎自动优化创建,不能人为干预是否为表创建Hash索引
上面也介绍了很多索引 但是。本文主要针对InnoDB存储引擎
# B+ tree 索引
B+tree 是在B树基础上的一种优化,其更适合做存储索引结构。在 B+tree 中,非叶子节点上仅存储键值,不存储数据;而所有数据记录均存储在叶子节点上,并且数据是按照顺序排列的。此外在 B+tree 中各个数据页之间是通过双向链表连接的,叶子节点中的数据是通过单向链表连接的。
# 按物理存储分类
# 聚簇索引
通俗点说B+树本身就是一个目录,聚簇索引就是按照每张表的主键构造一颗 B+tree,同时叶子节点中存放的就是整张表的行记录数据,聚集索引的叶子节点被称为数据页。它有俩个特点
- 使用记录主键值的大小进行记录和页的排序,这包括三个方面的含义:
- 页内的记录是按照主键的大小顺序排成一个单向链表。
- 各个存放用户记录的页也是根据页中用户记录的主键大小顺序排成一个双向链表。
- 存放目录项记录的页分为不同的层次,在同一层次中的页也是根据页中目录项记录的主键大小顺序排成 一个双向链表。
- B+ 树的叶子节点存储的是完整的用户记录。 所谓完整的用户记录,就是指这个记录中存储了所有列的值(包括隐藏列)。
InnoDB表要求必须有聚簇索引,默认在主键字段上建立聚簇索引,在没有主键字段的情况下,表的第一个非空的唯一索引将被建立为聚簇索引,在前两者都没有的情况下,InnoDB将自动生成一个隐式的自增id列,并在此列上建立聚簇索引。
# 非聚集索引(也叫二级索引、辅助索引)
非聚集索引的结构和聚集索引基本相同(非叶子结点存储的都是索引指针),区别在于叶子节点存放的不是行数据而是数据主键。因此在使用非聚集索引进行查找时,需要先查找到主键值,然后再到聚集索引中进行查找。
# 按字段特性分类
主键索引(PRIMARY KEY)
建立在主键上的索引被称为主键索引,一张数据表只能有一个主键索引,索引列值不允许有空值,通常在创建表时一起创建。唯一索引(UNIQUE)
建立在UNIQUE字段上的索引被称为唯一索引,一张表可以有多个唯一索引,索引列值允许为空,列值中出现多个空值不会发生重复冲突。普通索引(INDEX)
建立在普通字段上的索引被称为普通索引。全文索引(FULLTEXT)
MyISAM 存储引擎支持Full-text索引,用于查找文本中的关键词,而不是直接比较是否相等。Full-text索引一般使用倒排索引实现,它记录着关键词到其所在文档的映射。InnoDB存储引擎在MySQL5.6.4 版本中也开始支持Full-test索引。
前缀索引 前缀索引是指对字符类型字段的前几个字符建立的索引,而不是在整个字段上建立的索引,前缀索引可以建立在字段类型为 char、 varchar、binary、varbinary 的列上。
使用前缀索引的目的是为了减少索引占用的存储空间,提升查询效率。
# MySQL索引可能会失效的情况有以下几种:
- 索引列上使用了函数或表达式:如果在查询条件上使用了函数或者表达式,MySQL无法使用索引,因为他需要先计算表达式结果,然后在与索引值进行比较
- 使用了LIKE查询:如果使用LIKE查询并且没有以通配符开头,那么MySQL可以使用索引。但是,如果使用了通配符(例如%)开头,则MySQL将不得不扫描整个表。
- 数据类型错误:如果索引列的数据类型不匹配,MySQL可能会忽略索引。
- 多列索引时列顺序不正确:如果多列索引的列顺序不正确,MySQL可能无法使用该索引。
- 查询条件中包含OR运算符:当使用OR运算符时,MySQL可能无法使用索引来加速查询。
- 字符集不一致:如果索引列和查询条件中的字符集不一致,MySQL可能无法使用索引。