【MySQL】索引下推减少回表次数
一、简述索引下推
“索引下推”是数据库领域的一个术语,主要出现在MySQL(尤其是InnoDB存储引擎)中,英文名叫 Index Condition Pushdown,简称 ICP。就是过滤的动作由下层的存储引擎层通过使用索引来完成,而不需要上推到Server层进行处理。ICP是在MySQL5.6之后完善的功能
二、举例
假设有个user_consum表,有主键索引id和联合索引(name, phone),id是用户的消费记录,一个用户有很多条消费记录且name是用户昵称,可能撞车:
CREATE TABLE `user_consum` (`id` int unsigned NOT NULL AUTO_INCREMENT,`name` varchar(255) DEFAULT NULL,`phone` varchar(11) DEFAULT NULL,`gender` tinyint(1) DEFAULT NULL,`user_role` int DEFAULT 0,PRIMARY KEY (`id`),INDEX IDX_NAME_PHONE (name, phone)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
假设查询语句为:
SELECT * FROM user_innodb WHERE name = "luna" AND phone LIKE "%8848";
注意like是模糊匹配,无法用到索引。
此时假如在二级索引树中找到了几千个id即该用户有几千条消费记录,由于用户昵称可能撞车,这里不一定都是目标用户的,还需要手机尾号符合,那这里:
- 1,在二级索引树查到符合name的id后,回表到聚簇索引树(主键索引树),回表查询几千次,这些id可能还是离散不连续的,即几千次随机磁盘IO;
- 2,在存储引擎层查到几千行数据后,再将这些数据返到服务层根据过滤条件再筛选出尾号为8848的数据,发现其实只有10条数据符合
如果用上索引下推。
就是过滤的动作由下层的存储引擎层通过使用索引来完成,而不需要上推到Server层进行处理:
也就是在联合索引的查找中,即查找符合name = "luna"的数据,也直接在联合索引的叶子节点中去逐个判断phone的尾号是否为8848,然后找到那10条记录,再回表,从而将回表次数降低至10次!
在主键索引树中找到符合条件的10行数据后,再返给服务层10行,减少了存储引擎层到服务层的拷贝开销
,也减轻了服务层的过滤处理压力
!
三、如何查看是否用到了索引下推
执行:
EXPLAIN SELECT * FROM user_innodb WHERE name = "luna" AND phone LIKE "%8848";
如果 Extra 字段出现 Using index condition,说明用了索引下推(ICP)。
四、ICP的意义
- 减少回表次数,提升查询效率,尤其是对于大表和回表代价高的InnoDB表。
- 减少存储层到服务层的拷贝开销,减轻服务层的处理压力
- 只适用于InnoDB和MyISAM存储引擎(MySQL 5.6及以上版本)。
五、总结
索引下推(Index Condition Pushdown, ICP)是MySQL的一项索引优化技术,通过在索引遍历阶段尽量多地应用WHERE条件,减少回表次数,提高查询效率。
前置知识复习:
联合索引、最左匹配,回表、索引覆盖,
(1)联合索引:
(a,b)字段建立联合索引的话
按照a来进行排序,在a相等的情况下,才按b来排序
联合索引与最左匹配博客:
https://www.cnblogs.com/rjzheng/p/12557314.html
(2)最左匹配:
所谓最左原则指的就是如果你的 SQL 语句中用到了联合索引中的最左边的索引,那么这条 SQL 语句就可以利用这个联合索引去进行匹配,值得注意的是,当遇到范围查询(>、<、between、like前缀匹配)就会到此为止停止匹配(含当前这个)。
如有索引 KEY idx_abcd(a, b, c, d)
查询 WHERE a = 1 AND b = 2 AND c > 3 AND d = 4
a = 1 —— 用到了索引的第1列
b = 2 —— 用到了索引的第2列
c > 3 —— 范围查询(>),用到了索引的第3列
d = 4 —— 用不到索引,因为c是范围查询,后面的索引列就失效了 ,如果满足a = 1 AND b = 2 AND c > 3的行很多,那就要做很多匹配
所以sql应该这样写:WHERE a = 1 AND b = 2 AND d = 4 AND c > 3,这样都能用上索引
注意范围查询中like的情况
- 如果是前缀匹配(比如LIKE ‘abc%’),能用到索引。
- 如果是模糊匹配(比如LIKE ‘%6606’),无法走索引,因为无法确定起始位置,只能全表/全索引扫描
(3)回表
因为像联合索引还是单列普通索引这种非主键索引,都是查二级索引树,其value是主键id,所以如果要查一些在二级索引树没有的信息,就需要拿着主键id到聚簇索引(主键索引)树去查,这个过程就是回表。
回表的问题主要是,回表是一行数据回表一次,就要查一次聚簇索引!所以要想方法减少回表次数
比如假如查 select x from user where a=1 and c > 3;
其中x没有索引,a和c有索引,但是符合这个条件的有1000个数据,那回表会产生1000次查找,因为MySQL 只能从二级索引(idx_ac)中,依次取出每个满足条件的主键ID,每拿到一个主键值,就去聚簇索引树读取对应的整行数据,然后取出 x 字段。
因为二级索引返回的主键ID通常是离散的,这些主键对应的数据行物理上可能散布在磁盘不同位置,所以每次回表可能都需要一次磁盘I/O(如果不在缓冲池内),这就是“随机I/O”,效率低下(如果不离散的话倒是能直接在叶子节点顺序找到)
- InnoDB接口设计:MySQL的存储引擎接口本身是逐行取主键再查主表,没有批量取一批主键一次返回多行的API(虽然理论上可以优化,但InnoDB的实现就是这样)。
- 聚簇索引结构的限制:主表的行分散在磁盘不同位置,没办法保证物理上顺序访问,还是会有大量随机I/O。
也可以打开BKA批量回表机制(Batched Key Access
),比如每批次为500,那么对这500个主键id先排序,这样对于一些连续id就可以一次查找,减少随机I/O。注意:不是所有场景都能用BKA,主要在Join和二级索引回表时生效。
如果这种情况多,那最好就是给x也放到联合索引里,(a, c, x) — — 索引覆盖
(4)索引覆盖
如上user表里,如果
SELECT id, name, phone FROM user_info WHERE name = "userxxxx";
因为name和phone是联合索引,而id是主键,所以直接在一次就能在联合索引树上查到所有信息,所以不会有回表,这就是索引覆盖
(5)SQL执行过程简述
大部分情况下,MySQL会先从存储层获取主键ID对应的完整行数据,然后在服务层根据过滤条件进行过滤
- SQL解析&优化(服务层)SQL语句先在服务层被解析、生成执行计划,决定使用哪个索引、如何访问数据。
- 存储引擎访问数据(存储层)执行计划下发到存储层(如InnoDB),存储层根据执行计划,从磁盘或缓存(Buffer Pool)中读取行数据。
- 返回数据到服务层过滤存储层把读到的数据行返回到服务层,
服务层按照WHERE条件、HAVING条件等进行筛选、聚合等操作
。
相关文章:
【MySQL】索引下推减少回表次数
一、简述索引下推 “索引下推”是数据库领域的一个术语,主要出现在MySQL(尤其是InnoDB存储引擎)中,英文名叫 Index Condition Pushdown,简称 ICP。就是过滤的动作由下层的存储引擎层通过使用索引来完成,而…...

Artificial Analysis2025年Q1人工智能发展六大趋势总结
2025年第一季度人工智能发展六大趋势总结 ——基于《Artificial Analysis 2025年Q1人工智能报告》 趋势一:AI持续进步,竞争格局白热化 前沿模型竞争加剧:OpenAI凭借“o4-mini(高智能版)”保持领先,但谷歌&…...
DeepSeek模型高级应用:提示工程与Few-shot学习实战指南
引言 在DeepSeek模型的实际应用中,提示工程(Prompt Engineering)和Few-shot学习正成为提升模型性能的关键技术。相比全参数微调,这些技术能以更低成本实现领域适配。本文将深入解析DeepSeek模型的高级提示技巧、动态Few-shot实现方案,以及混合微调策略,帮助开发者在资源受…...
Android高级开发第三篇 - JNI异常处理与线程安全编程
Android高级开发第三篇 - JNI异常处理与线程安全编程 Android高级开发第三篇 - JNI异常处理与线程安全编程引言为什么要关注异常处理和线程安全?第一部分:JNI异常处理基础什么是JNI异常?检查和处理Java异常从C代码抛出Java异常异常处理的最佳…...
企业级应用狂潮:从Spotify到LinkedIn的Llama实战手册
当Spotify用Llama生成的个性化推荐文案让用户播放时长激增30%, 当LinkedIn靠开源框架将社交推荐延迟降低40%—— 企业级AI战场正经历从“技术炫技”到“利润引擎”的残酷蜕变。 核心数据:企业采用率爆发式增长(2025 Gartner调研) 指标2023年2025年增幅开源模型采用率42%87%…...

高效管理 Python 项目的 UV 工具指南
💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 持续学习,不断…...
QT中子线程触发主线程弹窗并阻塞等待用户响应
目录 QT中子线程触发主线程弹窗并阻塞等待用户响应一、使用QMetaObject::invokeMethod实现子线程安全触发主线程弹窗并阻塞等待:🔧 Qt多线程弹窗:安全阻塞等待方案(QMetaObject::invokeMethod详解)🧠 一、核…...

初识vue3(vue简介,环境配置,setup语法糖)
一,前言 今天学习vue3 二,vue简介及如何创建vue工程 Vue 3 简介 Vue.js(读音 /vjuː/,类似 “view”)是一款流行的渐进式 JavaScript 框架,用于构建用户界面。Vue 3 是其第三代主要版本,于 …...
HarmonyOS NEXT~鸿蒙开发工具CodeGenie:AI驱动的开发效率革命
HarmonyOS NEXT~鸿蒙开发工具CodeGenie:AI驱动的开发效率革命 一、CodeGenie概述 DevEco CodeGenie是华为鸿蒙开发生态中的一款AI辅助编程工具,集成于DevEco Studio IDE中,为开发者提供全方位的智能编程支持。这款工具通过AI技术…...

LeetCode-链表操作题目
虚拟头指针,在当前head的前面建立一个虚拟头指针,然后哪怕当前的head的val等于提供的val也能进行统一操作 203移除链表元素简单题 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode(…...

【ARM】MDK浏览信息的生成对于构建时间的影响
1、 文档目标 用于了解MDK的代码浏览信息的生成对于工程的构建是否会产生影响。 2、 问题场景 客户在MDK中使用Compiler 5对于工程进行构建过程中发现,对于是否产生浏览信息会对于构建时间产生一定的影响。在Options中Output栏中勾选了Browse Information后&#…...
Python模块中__all__变量失效问题深度解析
文章目录 Python模块中__all__变量失效问题深度解析一、__all__ 的正确作用场景二、__all__ 不起作用的常见原因1. 未使用 from ... import \* 导入2. __all__ 定义不完整或错误3. 子模块未正确导出4. Python 解释器缓存问题5. 相对导入路径错误 三、解决方案1. 确保使用 from …...

py爬虫的话,selenium是不是能完全取代requests?
selenium适合动态网页抓取,因为它可以控制浏览器去点击、加载网页,requests则比较适合静态网页采集,它非常轻量化速度快,没有浏览器开销,占用资源少。当然如果不考虑资源占用和速度,selenium是可以替代requ…...

docker B站学习
镜像是一个只读的模板,用来创建容器 容器是docker的运行实例,提供了独立可移植的环境 https://www.bilibili.com/video/BV11L411g7U1?spm_id_from333.788.videopod.episodes&vd_sourcee60c804914459274157197c4388a4d2f&p3 目录挂载 尚硅谷doc…...

SpringBoot高校宿舍信息管理系统小程序
概述 基于SpringBoot的高校宿舍信息管理系统小程序项目,这是一款非常适合高校使用的信息化管理工具。该系统包含了完整的宿舍管理功能模块,采用主流技术栈开发,代码结构清晰,非常适合学习和二次开发。 主要内容 这个宿舍管理系…...
深度解析 Dockerfile 配置:构建高效轻量的FastAPI 应用镜像
目录 引言 Dockerfile构建FastAPI镜像的示例 一、基础镜像选择:轻量与安全优先 二、元数据声明:镜像维护者信息 三、依赖管理:分层构建与缓存优化 1. 复制依赖文件 2. 安装依赖 四、应用代码复制:最小化镜像内容 五、启动…...

ICASSP2025丨融合语音停顿信息与语言模型的阿尔兹海默病检测
阿尔兹海默病(Alzheimers Disease, AD)是一种以认知能力下降和记忆丧失为特征的渐进性神经退行性疾病,及早发现对于其干预和治疗至关重要。近期,清华大学语音与音频技术实验室(SATLab)提出了一种将停顿信息…...
[蓝桥杯]春晚魔术【算法赛】
目录 输入格式 输出格式 样例输入 样例输出 运行限制 解决思路 代码说明 复杂度分析 问题描述 在蓝桥卫视春晚的直播现场,魔术师小蓝表演了一个红包魔术。只见他拿出了三个红包,里边分别装有 A、B 和 C 个金币。而后,他挥动魔术棒&a…...
LeetCode - 965. 单值二叉树
目录 题目 深度优先搜索方法 正确的写法 题目 965. 单值二叉树 - 力扣(LeetCode) 深度优先搜索方法 什么是深度优先搜索:深度优先搜索(DFS)是一种图或树的遍历算法,它从起始节点开始,尽可能深地沿着一条路径探索&…...

LabVIEW杂草识别与精准喷洒
基于LabVIEW构建了一套集成机器视觉、智能决策与精准控制的农业杂草识别系统。通过高分辨率视觉传感器采集作物图像,利用 LabVIEW 的 NI Vision 模块实现图像颜色匹配与特征分析,结合 Arduino 兼容的工业级控制硬件,实现杂草定位与除草剂精准…...
分布式不同数据的一致性模型
1. 强一致性(Strong Consistency) 定义:所有节点在任何时间点看到的数据完全一致,读操作总是返回最近的写操作结果。特点: 写操作完成后,所有后续读操作都能立即看到更新。通常需要同步机制(如…...
“application/json“,“text/plain“ 分别表示什么
这两个字符串:“application/json” 和 “text/plain” 是 MIME 类型(媒体类型),用于告诉接收方消息内容的格式,它们出现在 ContentType 字段中。 它告诉系统或程序:“这段数据是什么格式?” 格…...
SQL: 窗口滑动(Sliding Window)
目录 什么是“窗口”? 什么是“滑动”? 🔍 滑动窗口的核心: 🕒 什么是时间窗口?(Time Window) 时间窗口的基本结构 时间窗口的三种常见形式 📊 什么是行窗口&…...

学习日记-day20-6.1
完成目标: 知识点: 1.集合_Collections集合工具类 方法:static <T> boolean addAll(Collection<? super T> c, T... elements)->批量添加元素 static void shuffle(List<?> list) ->将集合中的元素顺序打乱static <T>…...

【音视频】 FFmpeg 解码H265
一、概述 实现了使用FFmpeg读取对应H265文件,并且保存为对应的yuv文件 二、实现流程 读取文件 将H265/H264文件放在build路径下,然后指定输出为yuv格式 在main函数中读取外部参数 if (argc < 2){fprintf(stderr, "Usage: %s <input file&…...
Linux 系统 Docker Compose 安装
个人博客地址:Linux 系统 Docker Compose 安装 | 一张假钞的真实世界 本文方法是直接下载 GitHub 项目的 release 版本。项目地址:GitHub - docker/compose: Define and run multi-container applications with Docker。 执行以下命令将发布程序加载至…...

软件测试|FIT故障注入测试工具——ISO 26262合规下的智能汽车安全验证引擎
FIT(Fault Injection Tester)是SURESOFT专为汽车电子与工业控制设计的自动化故障注入测试工具,基于ISO 26262等国际安全标准开发,旨在解决传统测试中效率低、成本高、安全隐患难以复现的问题,其核心功能包括…...

3D拟合测量水杯半径
1,目的。 测量水杯的半径 如图所示: 2,原理。 对 3D 点云对象 进行圆柱体拟合,获取拟合后的半径。 3,注意事项。 在Halcon中使用fit_primitives_object_model_3d进行圆柱体拟合时,输出的primitive_para…...
(21)量子计算对密码学的影响
文章目录 2️⃣1️⃣ 量子计算对密码学的影响 🌌🔍 TL;DR🚀 量子计算:密码学的终结者?⚡ 量子计算的破坏力 🔐 Java密码学体系面临的量子威胁🔥 受影响最严重的Java安全组件 🛡️ 后…...

Python训练打卡Day38
Dataset和Dataloader类 知识点回顾: Dataset类的__getitem__和__len__方法(本质是python的特殊方法)Dataloader类minist手写数据集的了解 在遇到大规模数据集时,显存常常无法一次性存储所有数据,所以需要使用分批训练的…...