一、MySQL中的回表是什么?

我的回答:

MySQL回表指的是在查询使用非聚簇索引也就是二级索引时,叶子节点只存储了索引列的值和主键Id,若要查询其他字段,就要根据主键去聚簇索引查询完整的数据。这个过程就是回表。比如用name的二级索引查age,要先通过name找到主键id,再用这个主键id查询age。回表会增加 IO ,所以可以建立覆盖索引来包含所需要的字段,避免回表。我练过用联合索引包含其他字段,减少了回表,查询快了不少~

回答重点(官方答案):

“回表” 是指在使用二级索引(非聚簇索引)作为条件进行查询时,由于二级索引中只存储了索引字段的值和对应的主键值,无法得到其它数据。如果要查询数据行中的其它数据,需要根据主键去聚簇索引查找实际的数据行,这个过程被称为回表。

二、MySQL中使用索引一定有效吗?如何排查索引效果?

我的回答:

MySQL中使用索引不一定有效,比如索引字段上有函数运算、使用了like '%xxx'这类前缀模糊匹配查询、类型不匹配,或者统计信息不准确等, 都可能导致索引失效。

排查索引效果,我们可以使用explain分析SQL执行计划,重点看type字段,(如all表示全表扫描)、key字段(是否为null),以及rows估算值

再通过show status like ‘Handler%’; 查看索引使用次数,对比查询前后的Handler_read_key和Handler_read_rnd_next等指标。之前我在练习时,发现一条SQL有索引,但是执行慢,用explain发现是因为对索引字段做了函数操作,调整后索引生效,查询效率显著提升,所以现在写SQL后都会习惯性用这些方法检验索引效果,避免出校“有索引但不生效”的情况。

回答重点(官方答案):

索引不一定有效。
例如查询条件中不包含索引列、低基数列索引效果不佳,或查询条件复杂且不匹配索引的顺序。
对于一些小表,MySQL 可能选择全表扫描而非使用索引,因为全表扫描的开销可能更小。
最终是否用上索引是根据 MySQL 成本计算决定的,评估 CPU 和 I/O 成本最终选择用辅助索引还是全表扫描。有时候确实是全表扫描成本低所以没用上索引。但有时候由于一些统计数据的不准确,导致成本计算误判,而没用上索引。

排查索引效果的方法:使用 EXPLAIN 命令,通过在查询前加上 EXPLAIN ,可以查看 MySQL 选择的执行计划,了解是否使用了索引、使用了哪个索引、估算的行数等信息。
主要观察 EXPLAIN 结果以下几点:

  • type(访问类型):这个属性显示了查询使用的访问方法,例如 ALL 、index 、range 等。当查询使用索引时,这个属性通常会显示为 index 或 range ,表示查询使用了索引访问。如果这个值是 ALL ,则表示查询执行了全表扫描,没有使用索引。
  • key(使用的索引):这个属性显示了查询使用的索引,如果查询使用了索引,则会显示索引的名称。如果这个值是 NULL ,则表示查询没有使用索引。
  • rows(扫描的行数):这个属性显示了查询扫描的行数,需要评估下扫描量。

扩展知识


确定索引真的生效了吗?
索引失效的场景有很多,也是面试官经常喜欢问的,可以根据具体场景进行排查,典型场景可以分为以下几点(实际索引的选择会根据 mysql 优化器的成本评定,答案最后会提到):

  1. 使用了联合索引却不符合最左前缀
    举个例子:小鱼对 user 表建立了一个联合索引为 name_age_id 的联合索引。
    他使用以下 SQL 查询 select * from user where age = 10 and id = 1;
    这样的写法恰恰不满足最左前缀原则,索引就失效啦。

  2. 索引中使用了运算
    例如这个 SQL select * from user where id + 3 = 8 。这样会导致全表扫描计算 id 的值再进行比较,使得索引失效。

  3. 索引上使用了函数也会失效
    例如:select * from user where LOWER (name) like 'cong%'; 。
    这样也会导致索引失效,索引参与了函数处理,会导致去全表扫描。

  4. like 的随意使用
    例如:select * from user where name like '% cong%'; 因为索引是从左到右来进行排序查找的,占位符直接放在了最左边开头,可能会导致直接全表扫描,这种情况就会导致索引失效。

  5. or 的随意使用
    user 当前只有一个索引 name 。此时执行以下 SQL:
    select * from user where name = 'cong' or age = 18; 这可能也会导致索引失效,因为 age 没有索引。

  6. 随意的字段类型使用
    不小心将 varchar 类型的 name 条件匹配了 int 类型字段。SQL 是这样的 select * from user where name = 1; ,在代码中涉及隐式转换!等于 select * from user where CAST (name AS signed int) = 1; ,这就变成了第三条索引上使用了函数,导致索引失效。
    除此之外还有隐式字符编码转换的问题,即联表查询的时候,如果不同表之间的关联字段字符编码不一致,也会导致隐式转换编码,等于变相用上了函数,使得索引失效。

  7. 不同的参数也会导致索引失效
    这个就是我在回答重点里面说的 “是否用上索引是根据 MySQL 成本计算决定的”。不同的参数 MySQL 评估成本不一致,有时候会选择使用索引,有时候会选择全表扫描,特别是在复杂查询(联表、子查询、需要回表等)的情况下。

比如根据商品从订单表查询,收集商品对应的所有买家的订单信息。如果传入的商品 id 是个热点商品,占据这家店铺 80% 的销量,那么本次查询对订单表很可能是全表查询,如果是冷门商品,则很可能是走索引查询。
8) 表中两个不同字段进行比较
例如这样的 SQL : select * from user where id > age; ,将 id 跟 age 字段做了比较,索引失效。
9) 使用了 order by
当 order by 后面跟的不是主键或者不是覆盖索引会导致不走索引。
为什么索引生效了反而查询变慢了呢?
确认是否选对了索引!MySQL 根据优化器会评估成本选择对应的索引,但有时候 MySQL 因为估计值不准确,导致选错了索引,因此查询速度反而更慢。

三、在MySQL中建立索引时需要注意哪些事项?

我的回答:

我会注意:

1.按需创建索引:根据实际查询需求,在where,join,order by等子句的字段上建索引,避免冗余。

2.会优先给唯一性高的,如id、手机号建立索引,像性别低选择性字段建立索引意义不大。

3.若是联合索引,遵循最左前缀原则,把选择性高的字段放在前面,比如(a,b,c)的索引能支持a、a+b、a+b+c的查询

4.避免失效场景,不在字段上使用函数,避免使用like %xxx、保证类型匹配,防止索引失效

5.权衡性能:索引会加快查询,但是会降低增删改的速度,还会占用磁盘空间,因此写入频繁的表要控制索引数量。

我练习的时候,给订单表的user_id 和 create_time建立联合索引,发现遵循最左原则的查询能命中索引,但是加了低选择性的status字段后反而失效,删除后性能恢复了,这让我明白索引设计要结合实际场景,不能盲目添加。

类型匹配解释:

加了低选择性的status字段,索引失效解释:

重点回答(官方答案)

  1. 不能盲目建立索引,索引并不是越多越好,索引会占用空间,且每次修改的时候可能都需要维护索引的数据,消耗资源。

  2. 对于字段的值有大量重复的不要建立索引。比如说:性别字段,在这种重复比例很大的数据行中,建立索引也不能提高检索速度。但是也不绝对,例如定时任务的场景,大部分任务都是成功,少部分任务状态是失败的,这时候通过失败状态去查询任务,实际上能过滤大部分成功的任务,效率还是可以的。

  3. 对于一些长字段不应该建立索引。比如 text、longtext 这种类型字段不应该建立索引。因为占据的内存大,扫描的时候大量加载至内存中还耗时,使得提升的性能可能不明显,甚至可能还会降低整体的性能,因为别的缓存数据可能因为它被踢出内存,下次查询还需要从磁盘中获取。

  4. 当数据表的修改频率远大于查询频率时,应该好好考虑是否需要建立索引。因为建立索引会减慢修改的效率,如果很少的查询较多的修改,则得不偿失。

  5. 对于需要频繁作为条件查询的字段应该建立索引。在 where 关键词后经常查询的字段,建立索引能提高查询的效率,如果有多个条件经常一起查询,则可以考虑联合索引,减少索引数量。

  6. 对经常在 order by、group by、distinct 后面的字段建立索引。这些操作通常需要对结果进行排序、分组或者去重,而索引可以帮助加快这些操作的速度。

扩展知识

MySQL 索引的最左前缀匹配原则是什么?

回答重点


MySQL 索引的最左前缀匹配原则指的是在使用联合索引时,

查询条件必须从索引的最左侧开始匹配。如果一个联合索引包含多个列,查询条件必须包含第一个列的条件,然后是第二个列,以此类推。
底层原理:因为联合索引在 B+ 树中的排列方式遵循 “从左到右” 的顺序,例如联合索引 (first_name, last_name, age) 会按照 (first_name, last_name, age) 的顺序在 B+ 树中进行排序。
MySQL 在查找时会优先使用 first_name 作为匹配依据,然后依次使用 last_name 和 age 。因此,组合索引能够从左到右依次高效匹配,跳过最左侧字段会导致无法利用该索引。
按照 (first_name, last_name, age) 的顺序在 B+ 树中的排列方式 (大致的示意图) 如下

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

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

相关文章

NeighborGeo:基于邻居的IP地理定位(一)

NeighborGeo:基于neighbors的IP地理定位 X. Wang, D. Zhao, X. Liu, Z. Zhang, T. Zhao, NeighborGeo: IP geolocation based on neighbors, Comput. Netw. 257 (2025) 110896, Abstract IP地址定位在网络安全、电子商务、社交媒体等领域至关重要。当前主流的图神经网络方法…

MySQL 8.0:窗口函数

一、基础知识 定义 窗口函数(Window Function)对查询结果集的子集(“窗口”)进行计算,保留原始行而非聚合为单行,适合复杂分析(如排名、累积和)。 基本语法: 函数名() OV…

AI 深度学习面试题学习

1.神经网络 1.1各个激活函数的优缺点? 1.2为什么ReLU常用于神经网络的激活函数? 1.在前向传播和反向传播过程中,ReLU相比于Sigmoid等激活函数计算量小; 2.避免梯度消失问题。对于深层网络,Sigmoid函数反向传播时,很容易就会出现梯度消失问题(在Sigmoid接近饱和区时,变换…

遇到该问题:kex_exchange_identification: read: Connection reset`的解决办法

kex_exchange_identification: read: Connection reset 是一个非常常见的 SSH 连接错误。它表明在 SSH 客户端和服务器建立安全连接的初始阶段(密钥交换,Key Exchange),连接就被对方(服务器)强制关闭了。 …

(论文蒸馏)语言模型中的多模态思维链推理

(论文总结)语言模型中的多模态思维链推理 论文名称研究背景动机主要贡献研究细节两阶段框架实验结果促进收敛性摆脱人工标注错误分析与未来前景 论文名称 Multimodal Chain-of-Thought Reasoning in Language Models http://arxiv.org/abs/2302.00923 …

React Native 接入 eCharts

React Native 图表接入指南 概述 本文档详细介绍了在React Native项目中接入ECharts图表的完整步骤,包括依赖安装、组件配置、数据获取、图表渲染等各个环节。 目录 1. 环境准备2. 依赖安装3. 图表组件创建4. 数据获取Hook5. 图表配置6. 组件集成7. 国际化支持8…

基于C#的OPCServer应用开发,引用WtOPCSvr.dll

操作流程: 1.引入WtOPCSvr.dll文件 2.注册服务:使用UpdateRegistry方法注册,注意关闭应用时使用UnregisterServer取消注册。 3.初始化服务:使用InitWTOPCsvr初始化 4.使用CreateTag方法,创建标签 5.读写参数使用下面三…

Java类加载器getResource行为简单分析

今天尝试集成一个第三方SDK,在IDE里运行正常,放到服务器上却遇到了NPE,反编译一看,原来在这一行:String path Test.class.getClassLoader().getResource("").getPath(); // Test.class.getClassLoader().ge…

【CodeTop】每日练习 2025.7.4

Leetcode 1143. 最长公共子序列 动态规划解决,比较当前位置目标和实际字符串的字母,再根据不同情况计算接下来的情形。 class Solution {public int longestCommonSubsequence(String text1, String text2) {char[] t1 text1.toCharArray();char[] t2…

ES6从入门到精通:Promise与异步

Promise 基础概念Promise 是 JavaScript 中处理异步操作的一种对象,代表一个异步操作的最终完成或失败及其结果值。它有三种状态:Pending(进行中)、Fulfilled(已成功)、Rejected(已失败&#xf…

数据结构:二维数组(2D Arrays)

目录 什么是二维数组? 二维数组的声明方式 方式 1:静态二维数组 方式 2:数组指针数组(数组中存放的是指针) 方式 3:双指针 二级堆分配 💡 补充建议 如何用“第一性原理”去推导出 C 中…

HAProxy 和 Nginx的区别

HAProxy 和 Nginx 都是优秀的负载均衡工具,但它们在设计目标、适用场景和功能特性上有显著区别。以下是两者的详细对比:1. 核心定位特性HAProxyNginx主要角色专业的负载均衡器/代理Web 服务器 反向代理/负载均衡设计初衷高性能流量分发高并发 HTTP 服务…

基于Java+SpringBoot的健身房管理系统

源码编号:S586源码名称:基于SpringBoot的健身房管理系统用户类型:多角色,用户、教练、管理员数据库表数量:13 张表主要技术:Java、Vue、ElementUl 、SpringBoot、Maven运行环境:Windows/Mac、JD…

【MySQL安装-yum/手动安装,卸载,问题排查处理完整文档(linux)】

一.使用Yum仓库自动安装 步骤1:添加MySQL Yum仓库 sudo rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-6.noarch.rpm步骤2:安装MySQL服务器 sudo yum install mysql-server -y步骤3:启动并设置开机自启 sudo systemctl start mysqld sudo systemct…

自定义线程池-实现任务0丢失的处理策略

设计一个线程池,要求如下:队列最大容量为10(内存队列)。当队列满了之后,拒绝策略将新的任务写入数据库。从队列中取任务时,若该队列为空,能够从数据库中加载之前被拒绝的任务模拟数据库 (TaskDa…

【NLP入门系列四】评论文本分类入门案例

🍨 本文为🔗365天深度学习训练营 中的学习记录博客🍖 原作者:K同学啊 博主简介:努力学习的22级本科生一枚 🌟​;探索AI算法,C,go语言的世界;在迷茫中寻找光芒…

Ubuntu安装ClickHouse

注:本文章的ubuntu的版本为:ubuntu-20.04.6-live-server-amd64。 Ubuntu(在线版) 更新软件源 sudo apt-get update 安装apt-transport-https 允许apt工具通过https协议下载软件包。 sudo apt-get install apt-transport-htt…

C++26 下一代C++标准

C++26 将是继 C++23 之后的下一个 C++ 标准。这个新标准对 C++ 进行了重大改进,很可能像 C++98、C++11 或 C++20 那样具有划时代的意义。 一:C++标准回顾 C++ 已经有 40 多年的历史了。过去这些年里发生了什么?这里给出一个简化版的答案,直到即将到来的 C++26。 1. C++9…

【MySQL】十六,MySQL窗口函数

在 MySQL 8.0 及以后版本中,窗口函数(Window Functions)为数据分析和处理提供了强大的工具。窗口函数允许在查询结果集上执行计算,而不必使用子查询或连接,这使得某些类型的计算更加高效和简洁。 语法结构 function_…

微型气象仪在城市环境的应用

微型气象仪凭借其体积小、成本低、部署灵活、数据实时性强等特点,在城市环境中得到广泛应用,能够为城市规划、环境管理、公共安全、居民生活等领域提供精细化气象数据支持。一、核心应用场景1. 城市微气候监测与优化热岛效应研究场景:在城市不…