索引大作战

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

索引的分类

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

  • 按照数据结构分类: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...

相关推荐
夜半被帅醒18 分钟前
MySQL 数据库优化详解【Java数据库调优】
java·数据库·mysql
不爱学习的啊Biao32 分钟前
【13】MySQL如何选择合适的索引?
android·数据库·mysql
破 风42 分钟前
SpringBoot 集成 MongoDB
数据库·mongodb
Rverdoser1 小时前
MySQL-MVCC(多版本并发控制)
数据库·mysql
m0_748233641 小时前
SQL数组常用函数记录(Map篇)
java·数据库·sql
dowhileprogramming1 小时前
Python 中的迭代器
linux·数据库·python
0zxm2 小时前
08 Django - Django媒体文件&静态文件&文件上传
数据库·后端·python·django·sqlite
Minxinbb7 小时前
MySQL中Performance Schema库的详解(上)
数据库·mysql·dba
mmsx7 小时前
android sqlite 数据库简单封装示例(java)
android·java·数据库
zpjing~.~9 小时前
Mongo 分页判断是否有下一页
数据库