MySQL数据库——索引潜规则(回表查询、索引覆盖、索引下推)

大家好,这里是编程Cookbook。本文详细介绍MySQL索引的三个潜规则——回表查询、索引覆盖、索引下推,以提升数据库的性能。

文章目录

    • 索引回顾
      • 聚集索引(Clustered Index)
      • 非聚集索引(Secondary Index/辅助索引/二级索引)
      • 为什么非主键索引的叶子节点存储主键值?
    • 回表查询
      • MyISAM和InnoDB的文件存储结构
    • 索引覆盖
    • 索引下推
    • 对比与关系
    • 优化建议


之前我们在《MySQL数据库——索引介绍》文章中介绍了按存储方式将索引划分为聚集索引和非聚集索引,由此引出了一些索引设计的潜规则(回表查询、索引覆盖、索引下推)。

  • 回表查询、索引覆盖、索引下推 是 InnoDB 的核心优化特性,尤其是索引下推,这是 InnoDB 的独有能力。
  • 如果使用 MyISAM 或 Memory 存储引擎,只能利用回表查询和索引覆盖,无法使用索引下推优化。

索引回顾

聚集索引(Clustered Index)

InnoDB 中的主键索引就是聚簇索引。

  • 叶子节点存储整行数据。
  • 索引即数据,查询到索引即查询到数据。
  • 表中行的物理顺序与键值的逻辑(索引)顺序相同。
  • 每个表只能有一个聚集索引,因为索引只能按照一种方式排序。

非聚集索引(Secondary Index/辅助索引/二级索引)

MyISAM 引擎中的所有索引都是非聚簇索引InnoDB 中,所有非主键索引都是非聚簇索引

  • 叶子节点存储的是主键值(对应行数据的PK)。
  • 查询时需要先通过非聚集索引找到主键值再通过主键回到聚集索引中查询完整数据行(即回表查询)。
  • 需要扫描两次索引树,因此效率较低。

为什么非主键索引的叶子节点存储主键值?

降低二级索引的维护成本:

  • 如果数据发生更新(如行移动或数据页分裂),只需修改(唯一的)聚簇索引,而无需重新构建非聚簇索引。

回表查询

MyISAM和InnoDB的文件存储结构

MyISAM 使用以下文件存储数据和索引:

  1. 表结构文件.frm 文件
    • 存储表的元数据(表定义、字段信息等)。
  2. 数据文件.MYD 文件
    • 存储实际的数据行。
  3. 索引文件.MYI 文件
    • 存储所有索引(包括主键索引、唯一索引、普通索引等)。

InnoDB 使用以下文件存储数据和索引:

  1. 表结构文件.frm 文件

    • 存储表的元数据(与 MyISAM 相同)。
  2. 表空间文件

    • 共享表空间:默认情况下,所有表的数据和索引存储在一个共享表空间文件(如 ibdata1)。
    • 独立表空间:启用独立表空间模式后,每个表的数据和索引存储在独立的 .ibd 文件中。

    注意:InnoDB的聚簇索引和非聚簇索引存储在同一个 .ibd 文件中,但在逻辑结构上是分开的。

    • 聚簇索引
      • 索引的叶子节点存储数据行本身。
      • 决定了数据的物理存储顺序。
    • 非聚簇索引(二级索引):
      • 索引的叶子节点存储主键值,用于通过主键值回表到聚簇索引获取数据行。

定义

  • 当 MySQL 使用非聚簇索引(Secondary Index)进行查询时,索引的叶子节点通常存储的是主键值或数据行的物理地址。

  • 如果查询的列不在该索引中,MySQL 必须通过索引获取主键值或物理地址,然后回到聚簇索引(或数据表)中查询所需的数据行,这个过程称为回表

场景

  • 查询的字段不完全被索引覆盖时,如果能够覆盖,则不需要回表。
  • 使用非聚簇索引查询时,必须回表获取完整数据。

示例

-- 假设表中有一个非聚簇索引 idx_name(列 name),主键为 id。
SELECT id, address FROM table WHERE name = 'John';
  • 查询条件中使用了索引列 name,但结果需要返回 idaddress
  • MySQL 需要先通过索引 idx_name 找到匹配的记录的主键值(id),再回表获取 address 数据。

索引覆盖

定义

  • 如果查询的列全部包含在索引中,MySQL 可以直接从索引中获取数据,而不需要回表,这种索引被称为覆盖索引
  • 优化目的:通过覆盖索引避免回表操作,从而提高查询效率。

场景

  • 查询字段较少,能够完全由索引覆盖时。
  • 常用于只需要索引列的统计或检索场景。

示例

-- 假设表中有一个复合索引 idx_name_address(列 name 和 address)。
SELECT name, address FROM table WHERE name = 'John';
  • 查询需要的列 nameaddress 都包含在索引 idx_name_address 中,MySQL 可以直接从索引中获取数据,无需回表。

索引下推

定义

  • 索引下推是 MySQL 5.6 引入的一种查询优化技术。
  • 在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数
  • 在使用索引进行查询时,MySQL 会将部分查询条件下推到存储引擎层,在存储引擎中通过索引过滤数据行,而不是将所有数据都返回到 MySQL 服务器层过滤。
  • 优化目的:减少返回 MySQL 层的数据量,提高查询效率。

场景

  • 查询中包含多个条件,而索引只支持部分条件时,MySQL 会尝试在存储引擎中尽量过滤更多的数据。

示例:

建立联合索引

CREATE INDEX `username` ON user2(`name`, `age`);

执行查询

SELECT * FROM user2 WHERE name LIKE 'j%' AND age = 99;

MySQL 5.5 执行流程(无索引下推):

  1. MySQL 的 Server 层调用存储引擎,找到第一个以 j 开头的 name
  2. 存储引擎使用 username 联合索引在 B+ 树中定位符合 name LIKE 'j%' 的记录。
  3. 存储引擎返回该记录的主键值(id),通过回表操作,去主键索引中找到完整数据行。
  4. 回表后,将数据返回给 Server 层。
  5. Server 层判断 age 是否等于 99:
    • 如果 age = 99,将记录返回给客户端。
    • 如果 age != 99,丢弃该记录。
  6. Server 层继续请求下一条记录,重复上述过程。

MySQL 5.6 执行流程(有索引下推):

  1. MySQL 的 Server 层调用存储引擎,找到第一个以 j 开头的 name
  2. 存储引擎使用 username 联合索引在 B+ 树中定位符合 name LIKE 'j%' 的记录。
  3. 存储引擎检查记录中是否包含 age 信息:
    • 如果 age = 99,存储引擎返回主键值(id),然后回表查询完整数据。
    • 如果 age != 99,存储引擎直接跳过该记录,不回表,继续读取下一条记录。
  4. 减少了不必要的回表操作,提高了查询效率。

执行过程对比:

步骤MySQL 5.5MySQL 5.6(索引下推)
过滤条件处理位置Server 层过滤 age = 99 条件存储引擎层先过滤 age = 99 条件
回表次数每一条符合索引条件的记录都会回表查询完整数据行只有符合所有条件的记录才会回表
性能增加了 I/O 开销,查询效率较低减少不必要的回表操作,提高查询效率

优点

  1. 减少数据传输:通过存储引擎过滤掉不符合条件的数据,减少返回 MySQL 层的数据量。
  2. 提升性能:尤其在范围查询或复合条件查询中,索引下推的效果更明显。

对比与关系

概念定义关键点
回表查询索引中无法满足查询需求,需要回到聚簇索引或数据表获取完整数据。增加 I/O 开销,尽量避免回表(如通过覆盖索引)。
索引覆盖查询所需列完全被索引覆盖,MySQL 可以直接从索引中获取需要的数据,无需回表。避免回表,提高查询效率。
索引下推将部分查询条件下推到存储引擎层,通过索引过滤更多数据,减少返回的数据量。优化复合查询条件,减少不必要的数据返回 MySQL 层

优化建议

  1. 尽量避免回表

    • 为常用查询创建覆盖索引,减少回表操作。
    • 使用精简的索引列,避免索引过大导致额外开销。
  2. 使用覆盖索引

    • 覆盖索引对性能提升显著,特别是常用的查询条件可以完全利用索引。
    • 针对常见查询场景设计复合索引,覆盖需要查询的所有列。
  3. 利用索引下推

    • 升级 MySQL 至 5.6 或更高版本,确保索引下推功能开启。
    • 在复杂查询条件中,通过索引下推尽量过滤无用数据。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VScode运行后出现黑窗口

原文链接:VScode运行出黑窗口 1.安装插件:C/C Compile Run 2.快捷键【CtrlShiftp】,点击【首选项:打开用户设置】

使用大语言模型(Deepseek)构建一个基于 SQL 数据的问答系统

GitHub代码仓库 架构 从高层次来看,这些系统的步骤如下: 将问题转换为SQL查询:模型将用户输入转换为SQL查询。 执行SQL查询:执行查询。 回答问题:模型根据查询结果响应用户输入。 样本数据 下载样本数据&#xf…

【前端小点】vue3项目内根据主题读取不同文件夹下的图片资源(图片文件)

项目要求实现一键换肤的功能,不仅仅是主题颜色上的替换,还有图片素材的替换,主题颜色替换的方案大同小异,下面仅对图片素材的一件替换进行方法描述。 主要思路 使用本地仓库对当前主题进行存储,系统根据主题去加载不同…

vxe-table实现动态列

vxe-table实现动态列 1.动态列解释2.解决步骤2.1将后端返回的动态列表头,按照格式拼接在固定列表头上2.2将后端返回的列表数据按照键值对格式组装 1.动态列解释 正常列表是有固定的列;我的需求是,最初只知道表格的固定两列,查询数…

Windows 11 使用容器(Docker Podman)

文章目录 背景1、相关网站1.1、WSL1.2、Docker1.3、Podman 2、环境3、安装部署3.1、安装 WSL3.2、Docker3.2.1、Docker Desktop3.2.1.1、安装3.2.1.2、拉取镜像3.2.1.3、启动容器 3.3、Podman3.3.1、安装3.3.2、使用3.3.3、异常处理 总结 背景 Windows 系统中使用容器&#xf…

UE_C++ —— Gameplay Modules

目录 一,Module Creation INI File Setup 二,Multiple Gameplay Modules 三,Limitations 编译成 DLL 的游戏相关类的集合;正如引擎本身由一组模块构成一样,每个游戏也是由一个或多个游戏模块构成的;这些…

蓝桥杯定时器实现led闪烁

step1.配置定时器,TIM1时高级定时,TIM2是通用定时器,用TIM2就行,用内部时钟源,记住相关公式,定时器中断配置时要使能,且生成代码后也要在mian中写使能函数 step2.写代码 配置生成代码后多出的…

二:前端发送POST请求,后端获取数据

接着一:可以通过端口访问公网IP之后 二需要实现:点击飞书多维表格中的按钮,向服务器发送HTTP请求,并执行脚本程序 向服务器发送HTTP请求: 发送请求需要明确一下几个点 请求方法: 由于是向服务器端发送值…

内外网文件传输 安全、可控、便捷的跨网数据传输方案

一、背景与痛点 在内外网隔离的企业网络环境中,员工与外部协作伙伴(如钉钉用户)的文件传输面临以下挑战: 安全性风险:内外网直连可能导致病毒传播、数据泄露。 操作繁琐:传统方式需频繁切换网络环境&…

elasticsearch在windows上的配置

写在最前面: 上资源 第一步 解压: 第二步 配置两个环境变量 第三步 如果是其他资源需要将标蓝的文件中的内容加一句 xpack.security.enabled: false 不同版本的yaml文件可能配置不同,末尾加这个 xpack.security.enabled: true打开bin目…

OpenCV二值化处理

1.1. 为什么需要二值化操作 二值化操作将灰度图像转换为黑白图像,即将图像中的像素值分为两类:前景(通常为白色,值为 255)和背景(通常为黑色,值为 0)。二值化的主要目的是简化图像&…

[Android]浏览器下载的apk文件无法识别无法安装问题

在Android电话机上,用浏览器下载apk进行版本更新,出现下载文件没被识别为apk,导致无法安装问题。 原来的下载链接: https://mojsetup.obs.cn-southwest-2.myhuaweicloud.com/callphone-release-1.0.4.apk 修改后的下载链接&…

如何使用SSH连接设备?很简单!

前言 小白发现最近写的文章都与SSH息息相关,于是就有了这一篇文章,免得在后续的文章又不断重复如何SSH连接设备。 有需要的小伙伴自然就会看到这里,也不会影响到其他小伙伴的阅读体验。 至于文章里的广告嘛……就当是小伙伴们给小白的一点…

【自学嵌入式(9)ESP8266网络服务器的使用】

ESP8266网络服务器的使用 ESP8266WiFi 库① WiFiClass② WiFiClient③ WiFiServer④ WiFiUDP ESP8266WiFiMulti 库① WiFiMulti ESP8266WebServer 库① P8266WebServer 网络服务器实例在浏览器中控制ESP8266指示灯将开发板引脚状态显示在网页中 在之前的文章中,曾经…

pytorch3d安装记录

官方安装教程: https://github.com/facebookresearch/pytorch3d/blob/main/INSTALL.md 通过pip 或conda 可以很容易安装上预编译好的包, 安装过程不会报错, 但是使用的时候就会报各种错误 ,原因是预编译好的包跟自己的环境不一定…

【CVPR2024-工业异常检测】PromptAD:与只有正常样本的少样本异常检测的学习提示

代码链接 摘要 摘要写作总结: 1.提出 两个关键点 (视觉语言模型【模型】 少量工业异常检测【方向】) 2.想要解决的问题 3.针对上述问题,本文提出了一种什么【方法】的什么【应用方面】方法【模型名】 4.具体讲方法的步骤 5.实验…

【PostgreSQL】如何通过调整PostgreSQL配置参数提高数据库性能

如何通过调整PostgreSQL配置参数提高数据库性能 1. 数据库初始性能2. 内存相关参数3. WAL(Write-Ahead Logging)相关参数4. 并行查询相关参数5. 连接相关参数6. 根据情况调整 1. 数据库初始性能 使用pgbench在更新PostgreSQL数据库配置前先测试下数据库…

AI Agent实战:打造京东广告主的超级助手 | 京东零售技术实践

前言 自2022年末ChatGPT的问世,大语言模型(LLM)技术引发全球关注。在大模型技术落地的最佳实践中,智能体(Agent)架构显现出巨大潜力,成为业界的普遍共识,各大公司也纷纷启动Agent技…

从【人工智能】到【计算机视觉】,【深度学习】引领的未来科技创新与变革

前几天偶然发现了一个超棒的人工智能学习网站,内容通俗易懂,讲解风趣幽默,简直让人欲罢不能。忍不住分享给大家,点击这里立刻跳转,开启你的AI学习之旅吧! 前言 – 人工智能教程https://www.captainbed.cn/l…

ChātGPT赋能的“SolidWorks工具箱”:重塑3D设计效率新标杆

ChātGPT精心打造的“SolidWorks工具箱”正逐步成为3D设计领域中的一颗璀璨新星,其集高效、便捷与创新于一身,为用户带来了前所未有的设计体验。以下是对这一革命性工具箱的深度剖析与美化呈现: 一、核心功能:重塑设计流程&#x…