再学mysql联合索引后面的列失效分析

2023年 7月 19日 54.5k 0

1 前言

基础不牢,地动山摇!!!索引是Mysql提高查询效率的一大利器(针对innodb引擎,以下相同),对于多条件查询的情况,我们可以创建联合索引进一步提高查询效率,但如果使用不当,联合索引就会失效或者使用联合索引不充分,前者比较好理解不进行深入分析,本文主要分析后者的情况。

2 准备工作

2.1 数据初始化

首先我们创建一个简单的表

CREATE TABLE `multiple_part_index_demo` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `c1` int(11) NOT NULL DEFAULT '0',
  `c2` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  KEY `idx_c1_c2` (`c1`,`c2`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;;

这个表创建了一个c1和c2的联合索引,继续添加一些初始数据

insert into `multiple_part_index_demo` (`c1`, `c2`) values(1, 2);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(1, 2);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(2, 4);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(3, 1);
insert into `multiple_part_index_demo` (`c1`, `c2`) values(3, 2);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(4, 1);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(6, 1);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(6, 2);
insert into `multiple_part_index_demo` (`c1`, `c2`) values(6, 4);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(8, 1);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(8, 1);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(8, 1);
insert into `multiple_part_index_demo` (`c1`, `c2`) values(8, 2);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(8, 2);
INSERT INTO `multiple_part_index_demo` (`c1`, `c2`) VALUES(8, 4);

通过执行 select * from multiple_part_index_demo;
最终的表数据显示如下

+----+----+----+
| id | c1 | c2 |
+----+----+----+
|  1 |  1 |  2 |
|  2 |  1 |  2 |
|  3 |  2 |  1 |
|  4 |  3 |  1 |
|  5 |  3 |  3 |
|  6 |  4 |  1 |
|  7 |  6 |  2 |
|  8 |  6 |  3 |
|  9 |  6 |  4 |
| 10 |  8 |  1 |
| 11 |  8 |  1 |
| 12 |  8 |  1 |
| 13 |  8 |  2 |
| 14 |  8 |  2 |
| 15 |  8 |  4 |
+----+----+----+

2.2 构建B+树

我们根据初始化的数据构建一棵B+树,这里不讲解如何构造B+树,可查阅其他资料帮助消化。Myqsl实际页大小为16kb,这里假设每页只能存放3条用户数据,超过3条页就会分裂,图中不同颜色代表不同的涵义,注意右上角的颜色说明。

联合索引原理.png

3 索引命中分析

我们都知道索引都是有序的,它会按字段值的大小升序排序,那如果是联合索引呢?比如给出的c1和c2列联合索引,首先会根据c1比较,如果比较c1就可以比出大小,那么c1小的就会排在前面,否则继续比较c2,c2比较小的排在前面,这个规律应该不难理解,但也非常非常重要,下面分析的索引使用列的情况就是依据这个规则。

3.1 等值查询

执行sql1

sql1: SELECT * FROM multiple_part_index_demo WHERE c1 = 6 AND c2 = 2;

查询结果如下,返回一条数据

+----+----+----+
| id | c1 | c2 |
+----+----+----+
|  8 |  6 |  2 |
+----+----+----+

我们再看下这条sql命中索引的情况

+----+-------------+--------------------------+------------+------+---------------+-----------+---------+-------------+------+----------+-------------+
| id | select_type | table                    | partitions | type | possible_keys | key       | key_len | ref         | rows | filtered | Extra       |
+----+-------------+--------------------------+------------+------+---------------+-----------+---------+-------------+------+----------+-------------+
|  1 | SIMPLE      | multiple_part_index_demo | NULL       | ref  | idx_c1_c2     | idx_c1_c2 | 8       | const,const |    1 |   100.00 | Using index |
+----+-------------+--------------------------+------------+------+---------------+-----------+---------+-------------+------+----------+-------------+

我们主要看看explain中的key_len,key_len表示执行sql命中索引使用列的字节数之和,这里的长度为8,因为c1和c2都是int类型,固定长度为4个字节,4 + 4 = 8,所以可以推出c1和c2都被使用到。
再根据B+树的结构来分析下,条件c1=6,在p1页里因为1 < 6 < 8,所以可以找到索引目录项(1, 2),而(8, 1)就被过滤掉了,下面的页过滤不符合条件的项原理相同,所以可以得到查找的路径和叶子节点的数据(p6页是叶子节点,括号内分别是c1和c2)

p1(1, 2) -> p2(6, 1) -> p6(6, 2)(6, 3)(6, 4)

因为最终的叶子节点的数据c1都是6,所以c2是有序的,此时可以根据c2=2条件来较少扫描行数(这里一条记录就是一行),我们分步骤来分析下c2的比较情况
(1) 首先与(6, 2)比较,2=2符合条件返回给客户端,因为2>=2,因此需要继续往下扫描比较
(2) 与(6, 3)比较,2!=3无需返回给客户端,并且2 p2(1, 2) -> p4(1, 2)(1, 3)(2, 1)

最后看下叶子节点是怎么过滤不符合条件的记录,c1包含了两个值1和2,导致c2并不是有序排列的,所以三条记录需要拿出来遍历判断c2是否等于2,具体步骤如下
(1) 与(1, 2)比较,2=2符合条件返回给客户端,因为2>=2,因此需要继续往下扫描比较
(2) 与(1, 3)比较,3!=2不符合条件,虽然2 p4(1, 2)(1, 3)(2, 1), p5(3, 1)(3, 3)(4, 1)

查询条件c2=2,分析下叶子节点的数据过滤具体步骤
(1) 与(1, 2)比较,2=2符合条件返回给客户端,因为2>=2,因此需要继续往下扫描比较
(2) 与(1, 3)比较,3!=2不符合条件,虽然2

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论