索引大作战

在日常工作中,对于慢查询的治理方法之一就是增加索引,索引的使用和学习在开发中是比较重要的内容,希望这篇文章能够彻底的梳理清楚。

索引的分类

索引的本质其实是一种数据结构,索引是在存储引擎层而不是在服务层实现的,所以没有统一的索引标准。其分类可以按照数据结构去分类,也可以按照物理存储进行分类,如下所示:

  • 按照数据结构分类:B+Tree 索引、Hash 索引和 Full-text 索引
  • 按照物理存储分类:聚集型索引和非聚集型索引
  • 按照逻辑分类:主键索引、唯一索引、联合索引

以下将重点介绍 B+Tree 索引、Hash 索引、聚集型索引和非聚集型索引

B+Tree 索引

一般我们说索引如果没有特指就是说 B+Tree 索引。基本上所有的存储引擎都支持它,InnoDB 和 MyISAM 存储引擎默认是 B+Tree 索引。

为什么默认使用 B+Tree 数据结构,而不是 B-Tree 或者是红黑树等数据结构?我们先看下 B+Tree 的数据结构

  1. B-Tree 索引非叶子节点存储数据,而 B+Tree 索引叶子结点不存储数据,只有在叶子结点存储数据,相对来说,相同层级存储的索引更多。相同也比红黑树的层级要低,层级低代表次数更少的 I/O 操作。
  2. 叶子结点采用连环式数据结构,可以进行范围查找

Hash 索引

Memory 存储引擎默认是 Hash 索引。Hash 索引的原理是给某列增加索引时,将这列数据进行 Hash 计算得到 Hash 值排列到 Hash 数组中,Hash 索引可以一次性定位到数据,其效率很高。Hash 索引虽然不需要多次进行磁盘 IO,但其也有一些缺点:

  1. 不能进行范围查找。Hash 索引计算的是经过 Hash 处理过的值,只能进行等式比较,不能用于范围查找,比如使用 order by 查询。
  2. 不支持最左匹配(不可使用部分索引进行查询)。每次计算需要扫描整个索引表,最左匹配是可以进行索引前缀进行查询,不必扫描整张索引表。
  3. Hash 索引值大量重复且数据量非常大时,其效率并没有 B+Tree 索引高

聚集型索引和非聚集型索引

聚集型索引和非聚集型索引都是使用 B+Tree 数据结构。

聚集型索引:是指在叶子结点存储完整的行数据,一张表只能有一个聚集型索引,一般是以主键为聚集型索引,如果新建表没有主键,则会创建一个隐含列(唯一)为聚集型索引。

非聚集型索引(辅助索引):叶子结点存储的不是完整的行数据,而是存储一个地址,一般是聚集型索引的地址,通过这个地址能找到聚集型索引,通过聚集型索引再找到完整的行数据。一个表可以有多个非聚集型索引。使用非聚集型索引查询,如果索引中包含查询的列,则直接返回,否则需要回表通过非聚集型索引找到其他查询数据。

联合索引查询

联合索引是指上文中提到的非聚集型索引,也就是辅助索引。联合索引是指索引中包含多个列,举个例子,假如建立索引如下所示:

sql 复制代码
alter table index_example add index idx_union(`name`, `age`, `position`);

数据存储的结构如下所示:

索引的存储会分别按照 name、age 和 position 排序,如果 name 相同,则根据 age 进行排序,name 和 age 相同,则根据 position 进行排序。

应该如何加索引

我们上面介绍了索引包括原理等一些基本情况,在日常开发中,加索引也有一些原则需要注意。以下是加索引的基本原则:

  1. 不要在数据量比较小的表建立索引。在查询时存储引擎会进行判断是否需要使用索引,数据量较小的表可能不会使用索引。
  2. 选择唯一主键索引。如果可以尽量使用主键索引或者唯一索引,将会更快的定位到数据(不需要回表)。
  3. 为经常需要排序、分组和联合操作的字段建立索引。group By、order by、distinct 和 union 等查询操作。
  4. 加索引要满足最左匹配原则。
  5. 尽量选择区分度高的字段增加索引。性别字段就不适合增加索引,不重复的比例越大,扫描的行数越少。索引是根据字段进行排序,0 和 1 的区别不大。
  6. 对字段使用函数不会走索引。

segmentfault.com/a/119000003...

www.cnblogs.com/hld123/p/14...

blog.csdn.net/weixin_4001...

github.com/wardseptemb...

相关推荐
.生产的驴12 分钟前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
AnsenZhu24 分钟前
2025年Redis分片存储性能优化指南
数据库·redis·性能优化·分片
oydcm41 分钟前
MySQL数据库概述
数据库·mysql
oioihoii1 小时前
C++23中if consteval / if not consteval (P1938R3) 详解
java·数据库·c++23
带娃的IT创业者1 小时前
《AI大模型趣味实战》基于RAG向量数据库的知识库AI问答助手设计与实现
数据库·人工智能
husterlichf2 小时前
MYSQL 常用数值函数 和 条件函数 详解
数据库·sql·mysql
我的golang之路果然有问题2 小时前
快速了解redis,个人笔记
数据库·经验分享·redis·笔记·学习·缓存·内存
卡皮巴拉爱吃小蛋糕3 小时前
MySQL的MVCC【学习笔记】
数据库·笔记·mysql
农民也会写代码3 小时前
dedecms织梦arclist标签noflag属性过滤多个参数
开发语言·数据库·sql·php·dedecms
m0_748232923 小时前
你还在手动画ER图吗?让SQL自动生成ER图,轻松解决作业难题!
数据库·sql·oracle