Mysql【索引覆盖、索引下推、索引合并、索引跳跃】介绍

news2025/2/25 9:07:50

        索引覆盖、索引下推、索引合并、索引跳跃都是Mysql对索引的优化手段,它们的思想就是尽量让查询数据走索引,那它们有什么区别呢?

一、首先介绍一下MySQL体系结构

上图来自MySQL官方文档。
通常把MySQL从上至下分为以下几层:

  • MySQL服务层:包括NoSQL和SQL接口、查询解析器、优化器、缓存和Buffer等组件。
  • 存储引擎层:各种插件式的表格存储引擎,实现事务、索引等各种存储引擎相关的特性。
  • 文件系统层: 读写物理文件。

MySQL服务层负责SQL语法解析、触发器、视图、内置函数、binlog、生成执行计划等,并调用存储引擎层去执行数据的存储和检索。我们后续说到的“索引下推”,它的“下”其实就是指将部分上层(服务层)负责的事情,交给了下层(存储引擎)去处理。

二、再介绍一下它们的概念

1、索引覆盖(Index Covering):索引覆盖是指查询的列包含在索引中,而不需要再次访问数据行。换句话说,查询可以直接从索引中获取所需的数据,而不必去查找实际的数据行。这样可以减少I/O操作,提高查询性能。

2、索引下推(Index Pushdown):索引下推是MySQL5.6中的新技术,是一种数据库查询优化技术,它利用了数据库引擎中的索引和过滤条件,将部分过滤工作下推到存储引擎层面进行处理,从而减少不必要的数据读取和传输。

        在传统的查询执行过程中,数据库引擎首先根据索引定位到符合过滤条件的数据行,并将这些数据行读取到内存中,然后再进一步进行过滤操作。而索引下推则再这一步骤中尽可能将过滤操作下推到存储引擎层面,避免将不符合条件的数据行读取到内存中,减少了IO次数。

索引下推(简称ICP)的条件:

  • 只能用于二级索引(secondary index);
  • explain显示的执行计划中type值(join 类型)为 range 、ref 、 eq_ref 或者 ref_or_null ;
  • 并非全部where条件都可以用ICP筛选,如果where条件的字段不在索引列中,还是要读取整表的记录到server端做where过滤;
  • ICP只可以用于MyISAM和InnnoDB存储引擎;

通过一下命令开启/关闭索引下推(mysql 5.6之后默认开启)

set optimizer_switch="index_condition_pushdown=off";

set optimizer_switch="index_condition_pushdown=on";

3、索引合并(Index Merge):索引合并是指数据库系统在执行查询时,利用多个索引来加速查询的过程。它通过同时使用多个索引,并将它们的结果合并,来获取最终的查询结果。索引合并通常在数据库系统无法选择一个最优的单一索引来满足查询需求时使用。

索引合并又包含三个算法,在explain中显示:

using intersect:
index merge intersection access algorithm(索引合并交集访问算法)。
对于每一个使用到的索引进行查询,查询主键值集合,然后进行合并,求交集,也就是AND运算。

using union:
index merge union access algorithm(索引合并并集访问算法)
容易看出,与上述的算法类似,不过是使用了or连接条件,求并集。
执行流程与index merge intersect 类似,依旧是查询了有序的主键集合,然后进行求并集。

using sort_union:
index merge sort sort-union access algorithm (索引合并排序并集访问算法)
根据索引查询得到主键集合,对于每个主键集合进行排序,然后求并集。

4、索引跳跃(Index Skip Scan):索引跳跃是一种优化技术,用于在多列索引中查找数据,即使查询不是以索引的第一列开始。当索引的第一列选择性很差时,索引跳跃可以跳过该列,并在后续列上进行查找。这可以减少所需的索引扫描次数,从而提高查询性能。

我们可以通过SHOW VARIABLES like '%optimizer_switch%'查看它们的开启情况

index_merge=on(是否开启索引合并),

index_merge_union=on(索引合并中的并集操作),

index_merge_sort_union=on(索引合并中的排序并集操作),

index_merge_intersection=on(索引合并中的交集操作),

engine_condition_pushdown=on(是否开启引擎条件下推功能),

index_condition_pushdown=on(索引条件下推),

mrr=on,mrr_cost_based=on,block_nested_loop=on,

batched_key_access=off,materialization=on,

semijoin=on,loosescan=on,firstmatch=on,duplicateweedout=on,

subquery_materialization_cost_based=on,use_index_extensions=on,

condition_fanout_filter=on,derived_merge=on,use_invisible_indexes=off,

skip_scan=on(索引跳跃),

hash_join=on,subquery_to_derived=off,prefer_ordering_index=on,

hypergraph_optimizer=off,derived_condition_pushdown=on

三、接下来创建一张员工表分别模拟一下这四个场景

1、首先我们创建了一个名为 employees 的表并创建相关索引,有 idnameagedepartment 四个字段。

-- 创建员工表
CREATE TABLE employees (
    ID int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(50),
    age int,
    department VARCHAR(50)
);

-- 创建name 和 age 列的联合索引
CREATE INDEX idx_name_age ON employees (name, age);

-- 创建部门列的单列索引
CREATE INDEX idx_department ON employees (department);

-- 创建覆盖了 name 和 department 列的联合索引
CREATE INDEX idx_name_department ON employees (name, department);

-- 创建年龄列的单列索引
CREATE INDEX idx_age ON employees (age);

2、加入一些模拟数据,向数据库插入20条数据

INSERT INTO employees (name, age, department) VALUES
('张三', 30, '人力资源部'),
('李四', 25, '市场部'),
('王五', 35, '财务部'),
('赵六', 28, '信息技术部'),
('刘七', 32, '人力资源部'),
('陈八', 27, '市场部'),
('周九', 40, '财务部'),
('吴十', 26, '信息技术部'),
('郑十一', 33, '人力资源部'),
('孙十二', 29, '市场部'),
('朱十三', 38, '财务部'),
('冯十四', 24, '信息技术部'),
('田十五', 31, '人力资源部'),
('马十六', 26, '市场部'),
('韩十七', 37, '财务部'),
('顾十八', 23, '信息技术部'),
('张十九', 29, '人力资源部'),
('李二十', 28, '市场部'),
('王二十一', 39, '财务部'),
('赵二十二', 27, '信息技术部');

1)索引覆盖场景:因为现在我们数据库有 name 和 age  列的联合索引,当我们只查询 name 和 age时,就会走索引覆盖。

-- 查询员工姓名和年龄【索引覆盖】
SELECT name, age FROM employees;

 我们用explain分析一下:

可以看到type显示的是index,表示查询语句在索引字段中遍历,再通过索引指向存储实际数据的地方,而不需要回表去磁盘遍历;

并且Extra字段里面显示Using index,这个就表示使用了索引覆盖;

2)索引下推场景:因为我们建立了(name,age)的联合索引,在一起作为条件过滤时,两个过滤条件都会下推到存储引擎层进行过滤,而无需返回服务层进行where过滤。

-- 查询姓张并且年龄>20的员工信息【索引下推】

SELECT  *  FROM employees WHERE NAME LIKE '张%'  AND age > 20 ;

我们先关闭索引下推,用explain分析一下:

set optimizer_switch="index_condition_pushdown=off";

可以看到使用了联合索引(name,age),Extra是Using where,也就是表示使用了where条件过滤。

过程:先在存储引擎层通过name索引查询以 '张' 开头的id,再回表查询这部分id的数据,再回到MySQL服务层使用where条件过滤age>20。(联合索引只能走name这一部分)

然后我们打开索引下推,再用explain分析一下:

set optimizer_switch="index_condition_pushdown=on";

可以看到使用了联合索引(name,age),并且Extra是Using index condition,也就是使用了索引下推。

过程:先在存储引擎层通过name索引查询以 '张' 开头的id,然后在这一批id中,继续在存储引擎层通过age索引查出年龄大于20的id,回表查询剩余id的数据,然后将符合条件的数据返回到MySQL服务层。(在储存引擎层过滤了name和age)

因为【使用了索引下推,是在符合name条件的id的基础上,再次筛选符合age条件的id】所以它符合条件的id数量一定小于等于【未使用索引下推,筛选出只符合name条件的id数量】,因为它们都要通过id回表,即索引下推最大限度减少了回表的次数。

3)索引合并场景:因为我们的name和department都是单列索引,在一起作为条件过滤时,会将两个结果集合并,得到最终的结果。

-- 查询姓张并且部门为市场部的员工信息【索引合并】

SELECT  * FROM employees WHERE name = '张三'  OR department = '市场部';

我们使用explain分析一下:

可以看到此时type为index_merge,为索引合并;

同时Extra中显示Using sort_union(idx_name_age,idx_department),表示索引合并中的排序并集操作。

它与索引下推的区别是:

        索引下推应用于联合索引,在存储引擎层面一层一层筛选出符合条件的id集合;而索引合并是应用于多个单列索引,并且将每个单列索引得到的id集合取交集,获得最后符合条件的id集合;

4)索引跳跃场景:因为现在我们数据库有 name 和 age  列的联合索引,当我们只查询 age时,它就会跳过name索引,直接走age索引,不必去匹配最左原则。

-- 查询年龄>20的员工信息【索引跳跃】

SELECT * FROM employees FORCE INDEX(idx_name_age) WHERE age > 20;

我们再次用explain分析一下:

发现它的type是ALL,并没有走索引;

这可能是由于数据量太少,执行器在优化阶段直接选择了全表扫描。

如果走了索引跳跃,应该是下图的场景,Extra为Using index for skip scan;

走索引跳跃有三个条件:

  1. Mysql的版本在8.0以上;
  2. 在优化器选项中设置skip_scan = on;
  3. Msql的优化器认为走索引跳跃的成本更低,效率更快。

索引跳跃可以参考:MySQL8.0优化(一)松散索引扫描/索引跳跃扫描ISS - 掘金 (juejin.cn)

ps:以下是我整理的java面试资料,感兴趣的可以看看。最后,创作不易,觉得写得不错的可以点点关注!

链接:https://www.yuque.com/u39298356/uu4hxh?# 《Java知识宝典》 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1585749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

arXiv苹果公司新论文“Self-Play”方法训练车辆道路merge的策略

arXiv苹果公司新论文“Self-Play”方法训练车辆道路merge的策略 附赠自动驾驶学习资料和量产经验:链接 苹果于2020年1月28日上传arXiv新论文“Towards Learning Multi-agent Negotiations via Self-Play“。 摘要: 做出复杂、鲁棒和安全的串行决策是智能…

使用 Python 的 LSTM 进行股市预测

目录 一、说明 二、为什么需要时间序列模型? 三、下载数据 3.1 从 Alphavantage 获取数据 3.1 从 Kaggle 获取数据 3.3 数据探索 3.4 数据可视化 四、将数据拆分为训练集和测试集 五、数据标准化 六、通过平均进行一步预测 6.1 标准平均值 6.2 指数移动平均线 6.3 如…

包拯断案 | 集群备份续集:三招解决定时备份延迟@还故障一个真相

今天,小编给大家讲述自己亲身遇到的一个数据库集群备份问题,希望帮助DBA运维的你绕开这个烦恼,轻松找到答案! 1、数据库集群在进行定时备份时(从节点备份),出现了主从延迟较大的告警&#xff0c…

泽众Testone自动化测试平台,测试用例支持单个调试执行,同步查看执行日志

泽众Testone自动化测试平台之前版本,测试用例批量和单个执行,必须要通过测试集操作执行,操作略繁琐,我们通过本轮优化升级,测试用例直接可以单个调试执行,同步查看执行日志,操作上去繁就简&…

Windows搭建Jellyfin影音服务结合内网穿透实现公网访问本地视频文件

文章目录 1. 前言2. Jellyfin服务网站搭建2.1. Jellyfin下载和安装2.2. Jellyfin网页测试 3.本地网页发布3.1 cpolar的安装和注册3.2 Cpolar云端设置3.3 Cpolar本地设置 4.公网访问测试5. 结语 1. 前言 随着移动智能设备的普及,各种各样的使用需求也被开发出来&…

windows ffmpeg7 通过rtsp拉取h265裸流

点击下边那个链接会转到github 下载完成后,添加include、lib到工程。 添加头文件: extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" #include "libavformat/avio.h" #inclu…

总体标准差、样本标准差、标准误(标准误差)

下面是样例: 参考文章如何做好SCI论文中的标准误差图 - 知乎 (zhihu.com)

鸿蒙HarmonyOS 与 Android 的NDK有什么不一样?

鸿蒙(HarmonyOS)和Android的NDK(Native Development Kit)是两个不同的概念,它们在设计理念、架构、开发方式和目标平台等方面存在着一些显著的不同。让我们详细比较它们的特点和区别。 1. 设计理念和架构: …

雪亮工程视频联网综合管理/视频智能分析系统建设方案(二)

一、我国雪亮工程当前建设需求 1)加强社会治安防控感知网络建设 加强社会治安防控智能感知网络建设,针对城中村、背街小巷、城乡结合部等重点区域建设安装视频监控设备,减少死角和盲区,与已有感知系统结合,形成高低搭…

【教程】四种方法将App打包为IPA文件类型

摘要 本教程总结了将App应用程序打包为IPA包的四种常用方法,包括Apple推荐的方式、iTunes拖入方法、自动编译脚本和解压改后缀名方法。每种方法都有其特点和适用场景,在实际开发中可以根据需求选择合适的方式进行打包。通过本教程,您将了解到…

windows10系统下TP-LINK万兆网卡属性配置高级说明

文章目录 打开配置属性说明ARP Offload:ARP地址解析协议卸载Downshift retries:降档重试次数Energy-Efficient Ethernet:高能效以太网Flow Control:流量控制Interrupt Moderation:中断调整Interrupt Moderation Rate:中断调节率IPv4 Checksum Offload:IPv4校验和卸载…

盲盒小程序带来的乐趣技术用代码如何形容?

星耀海贼萌袋抽卡潮玩小程序app盲盒软件定制 盲盒小程序带来的乐趣,技术人员可以用代码来形容,虽然代码本身并不具备直接描述情感的能力,但我们可以借助一些编程元素和概念来隐喻性地表达这种乐趣。 随机性的乐趣:盲盒小程序的核…

Jackson配置处理LocalDateTime、LocalDate等java8时间类型失效的问题解决

目录 前言 一、问题排查过程 1.1 SpringMvc是如何处理请求报文和响应报文 1.2 JacksonConfig配置排查 二、导致Jackson配置失效的原因 2.1 没有addSerializer 2.2 添加了EnableMvc注解 2.3 另外有地方配置了Jacksonhttpconver覆盖了配置 总结 前言 上一篇文章《使用Ja…

利用alibaba.item_get API接口,跨境电商如何快速获取商品详情?

利用alibaba.item_get API接口,跨境电商可以快速获取商品详情,为业务的开展提供有力支持。alibaba.item_get API接口是阿里巴巴开放平台提供的一项服务,它允许开发者通过调用API接口,获取阿里巴巴平台上商品的详细信息。以下是如何…

QT 线程之movetothread

上文列举了qt中线程的几种方法,其中2种方法最为常见。 这两种方法都少不了QThread类,前者继承于QThread类,后者复合QThread类。 本文以实例的方式描述了movetothread()这种线程的方法,将QObject的子类移动…

如何使用Tomcat+cpolar搭建本地站点并发布到公网分享好友远程访问

文章目录 前言1.本地Tomcat网页搭建1.1 Tomcat安装1.2 配置环境变量1.3 环境配置1.4 Tomcat运行测试1.5 Cpolar安装和注册 2.本地网页发布2.1.Cpolar云端设置2.2 Cpolar本地设置 3.公网访问测试4.结语 前言 Tomcat作为一个轻量级的服务器拥有强大功能,由于其可以实…

Python初级第二次作业

一、 def reverse(num):anumt0b0cnumwhile a//10>0:if a%10>0:t1aa//10print(t)for i in range(t,-1,-1):if c%100:b0else:b(c%10)*(10**i)c//10print(b) if bnum:return Trueelse:return Falsedef isPalind(num):kreverse(num)if kTrue:print(f"{num}是回文&…

分类模型决策边界、过拟合、评价指标、PR、ROC曲线

文章目录 1、线性逻辑回归决策边界1.2、使用自定义函数绘制决策边界1.3、三分类的决策边界1.4、多项式逻辑回归决策边界 2、过拟合和欠拟合2.2、欠拟合2.3、过拟合 3、学习曲线4、交叉验证5、泛化能力6、混淆矩阵7、PR曲线和ROC曲线 x2可以用x1来表示 1、线性逻辑回归决策边界 …

【找工作最强助手】全平台自动投简历脚本:(boss、前程无忧、猎聘、拉勾、智联招聘)

get-jobs【工作无忧】 💼自动投简历(Boss直聘、猎聘、拉勾、51job、智联招聘) 项目链接:https://github.com/loks666/get_jobs最新文档以上面的链接为主 特色功能 支持国内全部招聘平台(Boss直聘、猎聘、拉勾、51job、智联招聘)内置driver驱动&#xf…

各种拟合算法整理

各种拟合算法整理 1. 最小二乘法2. 霍夫变换3. RANSAC算法 本篇将介绍最小二乘法(Least Square)、霍夫变换(Hough Transform)和RANSAC(random sample consensus,随机抽样一致性算法)算法的原理、应用和代码。 如果已经知道了一组可靠的点,可以直接使用最…