MySQL:索引有哪些(清晰明了)

一提到索引,可能就会想到B+树索引、Hash索引、聚簇索引、主键索引、唯一索引、联合索引等等,但这些名词并不能混为一谈,他们有重复的部分,是从不同方面给索引取的名字。

**从数据结构上来讲:**B+树索引、Hash索引、Full-text 索引;

**从物理存储上来讲:**聚簇索引(主键索引)、二级索引(辅助索引);

**从索引字段上来讲:**主键索引、唯一索引、普通索引、前缀索引;

**从字段数量上来讲:**单列索引、联合索引;

那么我就从各个方面来介绍一下这些索引:

1、从数据结构上来讲

1.1 B+树索引

InnoDB 是在 MySQL 5.5 之后成为默认的 MySQL 存储引擎,B+Tree 索引类型也是 MySQL 存储引擎采用最多的索引类型。

B+Tree 是一种多叉树,叶子节点才存放数据,非叶子节点只存放索引,而且每个节点里的数据是按主键顺序存放的。每一层父节点的索引值都会出现在下层子节点的索引值中,因此在叶子节点中,包括了所有的索引值信息,并且每一个叶子节点都有两个指针,分别指向下一个叶子节点和上一个叶子节点,形成一个双向链表。

  • 高效的查找、插入和删除操作。
  • 优化的磁盘读写:B+树的结构减少了磁盘I/O操作,因为它将节点大小设置为与磁盘块相等,这减少了磁盘访问次数。
  • 支持范围查询:叶子节点的链表结构使得B+树特别适合执行范围查询,能够快速地遍历指定范围的所有值。

1.2 Hash索引

Memory引擎默认支持哈希索引,如果多个Hash值相同,出现哈希碰撞,那么索引就以链表方式存储。InnoDB或MyISAM存储引擎页支持Hash索引,但是需要通过伪Hash索引来实现,叫自适应Hash索引。

优点:

  • 查询速度非常快,只需一次哈希计算即可定位到相应的键值。
  • 适用于等值查询。

缺点

  • 无法支持范围查询,因为哈希索引不具备排序特性。
  • 无法进行模糊查询(例如 like 'xxx%')。
  • 内存占用较高,因为需要存储哈希值。

1.3 全文索引

Full-text索引一般使用倒排索引实现。倒排索引同B+tree索引一样,也是一种索引结构。

MySQL中InnoDB存储引擎在之前版本中是不支持全文检索的,要使用全文检索的话只能使用MySIAM存储引擎。在 MySQL 5.6.4 版本中InnoDB存储引擎才开始支持Full-text索引。

对于文本类型的大对象,或者较大的CHAR类型的数据,如果使用普通索引,那么匹配文本前几个字符还是可行的,但是想要匹配文本中间的几个单词,那么就要使用LIKE %word%来匹配,这样需要很长的时间来处理,响应时间会大大增加,这种情况,就可使用时FULLTEXT索引了,在生成FULLTEXT索引时,会为文本生成一份单词的清单,在索引时及根据这个单词的清单来索引。

  • 优点
    • 用于全文搜索,支持关键词匹配。
    • 适用于模糊查询和文本内容搜索。
  • 缺点
    • 占用空间较大。
    • 不适合精确匹配

2、从物理存储上来讲

2.1聚簇索引

主键索引的 B+Tree 的叶子节点存放的是实际数据,所有完整的用户记录都存放在主键索引的 B+Tree 的叶子节点里,当通过聚簇索引查询的时候,不需要回表,因为这个索引中存储了这张表中所有数据。

聚簇索引的创建:

  • 如果有主键,默认会使用主键作为聚簇索引的索引键(key);
  • 如果没有主键,就选择第一个不包含 NULL 值的唯一列作为聚簇索引的索引键(key);
  • 在上面两个都没有的情况下,InnoDB 将自动生成一个隐式自增 id 列作为聚簇索引的索引键(key);

2.2 非聚簇索引

非聚集索引的结构和聚集索引基本相同(非叶子结点存储的都是索引指针),区别在于叶子节点存放的不是行数据而是数据主键。因此在使用非聚集索引进行查找时,需要先查找到主键值,然后再到聚集索引中进行查找。这过程叫做回表。适合单行查找和特定值查找操作。可以有多个非聚集索引。

回表查询简单来说就是通过非聚集索引查询数据时,得不到完整的数据内容,需要再次查询主键索引来获得数据内容。

所以如果使用非聚集索引后还需要使用其他字段的(包括在where条件中或者select子句中),则需要通过主键索引回表到聚集索引获取其他字段。如果是非聚集索引可以满足SQL语句的所有字段的,则被称为全覆盖索引,没有回表开销。

避免回表查询问题,创建联合索引,如根据姓名查性别,那就建立一个姓名和性别的联合索引,那么再这个联合索引中进行查询的话,有查询字段性别,此时就不用回表,这种行为成为索引覆盖。索引覆盖就是指索引的叶子节点已经包含了查询的数据,满足查询要求,没必要再回表进行查询。

3、从索引字段上来讲

3.1 主键索引

  • 主键索引是一种特殊的唯一索引,要求索引列的值必须唯一且不可为空。
  • 每个表只能有一个主键索引,通常用于标识唯一性的列,如用户ID或订单号。

3.2 唯一索引

  • 唯一索引要求索引列的值必须唯一,但允许包含空值。
  • 适用于需要唯一性约束的列,如邮箱地址或用户名。

3.3普通索引

  • 普通索引是最基本的索引类型,没有特殊限制。
  • 可以在单列上创建,也可以是组合索引。
  • 适用于经常需要查询的列。

3.4前缀索引

  • 前缀索引是指对字符类型字段的前几个字符建立的索引,而不是在整个字段上建立的索引,前缀索引可以建立在字段类型为 char、 varchar、binary、varbinary 的列上。
  • 使用前缀索引的目的是为了减少索引占用的存储空间,提升查询效率。

4、从字段数量上来讲

4.1 单列索引

  • 单列索引是最基本的索引类型,仅对一个列进行索引。
  • 适用于经常需要查询的单个列。
  • 例如,在用户表中对年龄(age)字段建立单列索引。

4.2联合索引

  • 联合索引由多个列组成,可以同时对多个列进行索引。
  • 适用于组合搜索,效率高于单列索引。
  • 注意选择联合索引的列顺序,最左前缀原则。

最左前缀原则

查询中的过滤条件必须从索引的最左边开始,并且不能跳过中间的列。只有当查询条件与索引的最左前缀完全匹配时,索引才能被充分利用。

比如,如果创建了一个 (a, b, c) 联合索引,如果查询条件是以下这几种,就可以匹配上联合索引:

  • where a=1;
  • where a=1 and b=2 and c=3;
  • where a=1 and b=2;

需要注意的是,因为有查询优化器,所以 a 字段在 where 子句的顺序并不重要。

但是,如果查询条件是以下这几种,因为不符合最左匹配原则,所以就无法匹配上联合索引,联合索引就会失效:

  • where b=2;
  • where c=3;
  • where b=2 and c=3;

上面这些查询条件之所以会失效,是因为(a, b, c) 联合索引,是先按 a 排序,在 a 相同的情况再按 b 排序,在 b 相同的情况再按 c 排序。所以,b 和 c 是全局无序,局部相对有序的,这样在没有遵循最左匹配原则的情况下,是无法利用到索引的。

相关推荐
梵法利亚35 分钟前
Ubuntu-docker安装mysql
mysql·ubuntu·docker
炬火初现1 小时前
Etcd的安装与使用
数据库·etcd
IT猿手1 小时前
2025最新群智能优化算法:云漂移优化(Cloud Drift Optimization,CDO)算法求解23个经典函数测试集,MATLAB
开发语言·数据库·算法·数学建模·matlab·机器人
程序员爱钓鱼1 小时前
Go 语言高效连接 MySQL 数据库:从入门到实战
后端·mysql·go
雷渊1 小时前
深入分析理解mysql的MVCC
java·数据库·面试
Paparazi灬1 小时前
RocksDB写流程各种场景下的处理逻辑和线程交互时序
数据库
白熊一号2 小时前
Hi, DeepSeek 带我通过实战学习SQL入门知识
sql·mysql
神经星星2 小时前
【vLLM 教程】使用 TPU 安装
数据库·人工智能·机器学习
hjehheje3 小时前
clickhouse查询效率低
数据库·人工智能
七七powerful3 小时前
ClickHouse 中出现 DB::Exception: Too many parts 错误
java·前端·数据库