索引覆盖

原文:MySQL 覆盖索引详解

1. 什么是索引?

索引是方便存储引擎快速找到记录的一种数据结构,通俗来说类似于书本的目录,方便快速查询书本中的内容。

2. 索引的有哪些种类?

索引的种类这里只罗列出 InnoDB 支持的索引:主键索引 (PRIMARY),普通索引 (INDEX),唯一索引 (UNIQUE),组合索引,总体可划分为主键索引和非主键索引两类,InnoDB 中主键索引为聚簇索引(clustered index),其余都为非聚集索引,也被称为辅助索引或二级索引(secondary index)。

3. InnoDB 中不同索引的组织结构是怎样的?

索引可划分为主键索引和非主键索引,这两种索引有哪些区别?

我们这里建立一张学生表,其中字段 id 设置主键索引、name 设置普通索引、age(无处理),并向数据库中插入 4 条数据:

CREATE TABLE `student` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增主键',
  `name` varchar(32) COLLATE utf8_bin NOT NULL COMMENT '名称',
  `age` int(3) unsigned NOT NULL DEFAULT '1' COMMENT '年龄',
  PRIMARY KEY (`id`),
  KEY `I_name` (`name`)
) ENGINE=InnoDB;

INSERT INTO student (name, age) VALUES("小赵", 10),("小王", 11),("小李", 12),("小陈", 13);

此时数据库里数据为:

img

每一个索引在 InnoDB 里面对应一棵 B+ 树,此时就存着两棵 B+ 树:

img

可以发现叶子节点中,主键索引存储了整行数据,而非主键索引中存储的值为主键 id,在我们执行如下 SQL 时:

SELECT age FROM student WHERE name = '小李';

流程为:

  1. 在 name 索引树上找到名称为小李的节点,id 为 03
  2. 从 id 索引树上找到 id 为 03 的节点,获取所有数据
  3. 从数据中获取字段名为 age 的值,返回 12

流程中,从非主键索引树搜索回到主键索引树搜索的过程称为回表

4. 什么是覆盖索引?

覆盖索引(covering index,或称为索引覆盖)即从非主键索引中直接能查到的记录,而不需要查询主键索引中的记录,避免了回表的产生减少了树的搜索次数,显著提升性能。

5. 如何使用是覆盖索引?

假如业务需求中要求根据名称获取学生的年龄,并且该搜索场景非常频繁,那么我们先删除掉之前以字段 name 建立的普通索引,以 name 和 age 两个字段建立联合索引,SQL 命令与建立后的索引树结构如下:

ALTER TABLE student DROP INDEX I_name;
ALTER TABLE student ADD INDEX I_name_age(name, age);
img

那在我们再次执行如下 SQL 后:

SELECT age FROM student WHERE name = '小李';

流程为:

  1. 在 name,age 联合索引树上找到名称为小李的节点
  2. 此时节点索引里包含信息 age 直接返回 12

6. 如何确定数据库成功使用了覆盖索引呢?

当发起一个索引覆盖查询时,在 explain 的 extra 列可以看到using index的信息,表明成功使用了覆盖索引:

img

扩展:索引下推

posted @ 2024-06-28 16:13  Higurashi-kagome  阅读(5)  评论(0编辑  收藏  举报