翻译翻译什么TMD叫EXPLAIN

数据科学家面试本质是可信度传递系统 数据科学家不是算法工程师,而是技术、业务与影响力三重能力的融合体。其核心在于构建‘可信度传递系统’:用可验证的数据证据链替代主观判断,以系统性风险预判支撑模型上线决策。这要求候选人既掌握特征工程、模型评估、SQL与分布式系统等硬技能,更需具备将业务问题翻译为数据问题的能力,并能向非技术人员清晰传达技术价值。真实面试中淘汰率最高的环节往往不是算法题,而是终面——当被问‘如果模型明天上线,你敢签字吗’,答案暴露的是工程敬畏心、业务共情力与组织推动力。本文聚焦数据科学岗位特有的能力三角:技术深度×业务理解×影响力 阅读详情

其实网上有很多写的很好的sql优化文章,全面细致,但是都遗漏了一个问题,只教了大家怎么治病,没教怎么看病,这就好比一个饱读医书的大夫,病人往这一坐,望闻问切全都不会,一身的本事不知道该用哪个?
急死个人了。
所以今天就聊聊怎么看病,也就是如何看MySQL的执行计划。

EXPLAIN

当客户端发送给服务端一条sql语句后,并不是拿过来就执行的,而是先经过优化器选取最优的方案,比如表的读取顺序,索引实际是否被使用,表之间的引用等。
而优化后的执行方案就称之为执行计划。

EXPLAIN的作用就是查看执行计划,使用起来非常简单,无论是select insert update delete,都是只需要在前面加explain。

-- items : 商品主数据表
explain select * from items;

执行后的结果如下(为方便查看,使用树形结构展示):

左面就是执行计划的列名,我们的学习的关键就是要知道每列的含义。

右面是对应的值,在实际开发中通过分析值来诊断sql语句的问题。

看懂执行计划

id

select的执行顺序,怎么理解呢?看下面的sql:

explain
  select *
  from items_img
  where item_id =
        (select id from items where item_name like '蛋糕');

共有两个查询,哪个先执行呢,可以通过id来判断:

  • id 越大,优先级越高,越先执行。
  • id相同的情况下执行顺序是由上到下。

验证一下:

可以看到id=2,对应items表,先执行。

select_type

观察刚才的输出结果,发现子查询的select_type值是不一样的,分别是什么意思呢?

顾名思义,应该是查询类型的意思,我们只要知道了某个小查询的select_type属性,就知道了这个小查询在整个大查询中扮演了一个什么角色。

PRIMARY是指查询中包含子查询,并且该查询位于最外层,而SUBQUERY翻译过来就是子查询。上面的SIMPLE则是最普通,最简单的查询。

还有一些其他的值如下:

  • DERIVED : 表示在from中包含子查询
  • UNION : 对于包含UNION或者UNION ALL的大查询来说,除了最外层的查询会被标记为PRIMARY,其余都会被标记为UNION。
  • UNION RESULT : 表示UNION查询中的临时表。
  • MATERIALIZED:IN或EXISTS后的查询。
补充说明:
MATERIALIZED翻译过来是物化的意思,即将子查询结果集中的记录保存到临时表的过程。
临时表称之为物化表。正因为物化表中的记录都建立了索引(基于内存的物化表有哈希索引,基于磁盘的有B+树索引),通过索引执行IN语句判断某个操作数在不在子查询结果集中变得非常快,从而提升了子查询语句的性能。

table

这个无需多说,表明这一行的数据是关于哪个表。

partitions

这里先介绍一下分区表的概念,和我们常说的分库分表不同。

分区表是指将数据文件在磁盘上进行分区,将一个大文件分成多个小文件。可以优化查询性能,特别是对于count查询可以并发统计,还可以通过指定分区快速删除废弃数据。

分区类型:

  • RANGE分区:根据给定一个连续的区间进行分区。在删除旧数据时特别有用。
  • LIST分区:根据具体数值分区。假设某商品销售在华东,华中,华北三个战区,按照战区分区,在where查询时只需要指定分区即可。
  • HASH分区:根据对固定整数取模来分区,这就要求数据分布比较平均。Hash分区也存在与传统Hash分表一样的问题,可扩展性差。MySQL也提供了一个类似于一致性Hash的分区方法-线性Hash分区,只需要在定义分区时添加LINEAR关键字。
  • KEY分区:与Hash分区很相似,只是Hash函数不同。

看一个创建分区表的示例:

-- 创建user表
 create table user_partitions (
   id int auto_increment, 
   name varchar(12),
   primary key(id)
 )
 -- 按照id分区,id<100 p0分区,其他p1分区
 partition by range(id)(
     partition p0 values less than(100),
     partition p1 values less than maxvalue
 );

回到执行计划,partitions这列表明数据在哪个分区。

type

代表访问类型,即如何查找数据,结果值从最好到最坏依次是:

system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery> range > index>all

可以只记住简化版的:

system > const > eq_ref > ref > range > index>all

生产环境一般需要达到ref或range 级别。依次给大家介绍下:

system:表中只有一行记录(等于系统表),平时基本不会出现。

const:通过索引一次就找到了。

示例:

explain
    select * from items where id = 'bingan-1001';

eq_ref:唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。

ref:非唯一索引扫描,返回匹配某个单独值的所有行。

首先商品表给销量建一个索引,但不是唯一索引。

sql如下:

explain
    select * from items where sell_counts = 3308;

range:只检索给定范围的行。

还是销量这列,sql如下:

explain
    select * from items where sell_counts between 3000 and 10000;

index:当查询的结果全为索引列的时候。

explain
    select id,sell_counts from items;

all:全表扫描

explain
    select * from items where sell_counts;

null:是不是没想到还会有空的时候,空的意思是我都不需要查表,只需要查索引就能搞定,比如:

explain select min(id) from items;

table也是空,说明只查了索引。

possible_keys

翻译一下就是可能用到的key,但不一定真正会用到,有可能是因为MySQL认为有更合适的索引,也可能因为数据量较少,MySQL认为索引对此查询帮助不大,选择了全表查询。

如果想强制使用或不使用某个索引,可以在查询中使用 force index、ignore index。

key

真正用到的索引。

通过对比possible_keys和key,可以观察所建的索引书否被使用,即索引是否合理,从而进行优化。

索引不是建的越多越好,可能使用的索引越多,查询优化器计算查询成本时就得花费更长时间,所以如果可以的话,尽量删除那些用不到的索引。

对于线上已经存在大量数据的表,不要轻易增加索引,因为会增大数据库的压力。

key_len

表示索引使用的字节数,通过这个值可以算出具体使用了索引中的哪些列。

看一个案例:

新建一个联合索引

执行如下sql

explain
    select * from items where sell_counts=300;

看一下结果

显然是用到了联合索引,但是具体用到那一列呢,发现ken_len是4,正好是一个int类型的长度,也是就只使用了sell_counts这列。

修改一下sql

explain
    select * from items where sell_counts=300 and item_name='好吃蛋糕甜点蒸蛋糕';

执行结果

索引不变,ken_len变为134,怎么来的呢?

需要先看一下item_name的长度是32。

还需要知道字符编码是是什么?show variables like 'character%';

utf8mb4是个啥呢,简单说就是它才是MySQL中真正的utf8,而MySQL中的utf8是一种“专属的编码”,它能够编码的Unicode字符并不多。

这其实MySQL的一个bug,utf8mb4是用来修复的。

言归正传,用字段长度*编码占字节=总的字节数。即32*4=128。(latin1 占用一个字节,gbk 占用两个字节,utf-8 占用三个字节)。

但是这还每完,因为varchar是可变长度的,还需要两位存储真正的长度。这样加上int的四个字节,刚好134,由此推断出用到了sell_conts和item_name两列(128+2+4=134)。

另外由于字符串是可以存储空值的,所以还需要一个标志位来存储是否为空,但是在本例中,item_name是非空列,所以不再加一。

ref

展示与索引列作等值匹配的值是什么,比如一个常数或者是某个列。

explain
    select * from items i where id = 'cake-1001';

这样是一个常数

explain
    select * from items i left join category c
    on c.id = i.cat_id;

这样是一个列

rows

大致所需要读取的行数。

如果查询优化器决定使用全表扫描的方式对某个表执行查询时,代表预计需要扫描的行数。

如果使用索引来执行查询时,就代表预计扫描的索引记录行数。

explain
    select * from items i where sell_counts >  100;

filtered

通过表条件过滤出的行数的百分比估计值。

Extra

顾名思义,Extra列是用来说明一些额外信息的,我们可以通过这些额外信息来更准确的理解MySQL到底将如何执行给定的查询语句,也是很重要的一列。主要有以下值:

  • Using index:查询的列被索引覆盖,也就是使用了覆盖索引,会很快。
  • Using where:表明使用了 where 过滤。
  • Using where Using index:查询的列被索引覆盖,但是不是索引的前导列(第一列)。
  • NULL:查询的列未被索引覆盖,并且where筛选条件是索引的前导列。即用到了索引,但还不够,需要回表(先拿到id,通过id再查一遍)
  • Using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围
  • Using temporary:用到了临时表,比如去重,分组。
  • Using filesort:排序列未创建索引。
  • Using join buffer (Block Nested Loop):关联查询时,当被驱动表没有索引时,MySQL一般会为其分配一块名叫join buffer的内存块来加快查询速度,也就是我们所讲的基于块的嵌套循环算法。
explain
    select * from items i left join category c
    on c.name = i.item_name;

还会有比如No tables used(没有from子句)等等。

总结

ok,EXPLAIN的所有列就已经聊完了,小结一下:

列名含义
id执行顺序
select_type查询类型
table用到的表
partitions用到的分区
type访问类型
possible_keys可能用到的索引
key真实用到的索引
key_len索引用到的字节数
ref与索引列匹配的值
rows估计扫描的行数
filtered筛选比
Extra额外补充信息

 

金九银十后端面试备战指南:从原理到实战的系统提升 技术面试不仅考察知识记忆,更关注候选人对原理的理解与工程实战能力。以Java集合、MySQL索引、Redis缓存等高频考点为例,面试官往往通过层层追问检验候选人是否真正理解数据结构设计、事务隔离机制与缓存一致性等核心概念。掌握B+树为何适用于磁盘存储、MVCC如何实现快照读、缓存穿透与雪崩的取舍等原理,才能体现技术深度。在项目复盘环节,用数据量化优化效果、讲清排查链路,是区分候选人的分水岭。系统设计与场景题则需从容量估算、技术选型到容错扩展的完整思考。金九银十窗口期,从基础原理到项目表达的系统化备战指南,正 阅读详情

相关推荐

【Hyper-V】虚拟机网络配置全解析:从端口映射到固定IP实战

本文全面解析Hyper-V虚拟机网络配置,从理解虚拟交换机三种模式(外部、内部、专用)的底层逻辑入手,指导用户创建稳定的内部/NAT网络,并详细演示如何在Linux与Windows虚拟机中配置固定IP。文章进一步深入讲解端口映射原理与netsh命令实战,以及双网卡配置和PowerShell自动化脚本等高级技巧,帮助用户彻底解决虚拟机网络“失联”问题,实现灵活可控的网络环境。

weixin_29290947的博客 269

程序员成长路线图:5大层级20+核心能力

编程是一场马拉松,不是短跑。保持好奇心,持续学习,享受解决问题的过程。

热爱技术与前沿创新,深耕科技领域,在科创中精进自我;探索技术乐趣,分享技术干货与成长心得,以技术为伴,热爱生活,在科创与生活中双向成长。 302

Transformer实战(40)——Transformer时间序列数据建模

Transformer 因其在自然语言处理 (Natural Language Processing, NLP) 任务中的优异表现而被广泛应用,其主要优势在于能够有效建模时间序列数据。这些数据可以是文本,也可以是非文本。本节将介绍如何使用 Transformer 进行时间序列数据建模和预测,将学习时间序列的基本概念,并在此基础上使用一个简单的模型,用以初步了解时间序列数据,并为各种预测任务奠定基础。

盼小辉丶的博客 2346

【DOM】DOM概述及DOM操作之如何查找元素_01

DOM是一套专门操作网页内容的对象和函数的集合。今后只要想用JS程序操作网页内容,都必须使用DOM提供的对象和方法。DOM使JS有访问HTML的能力,能够实现对HTML中内容的操作。使用JS操作DOM时分为三个方面:DOM Core(核心)、HTML-DOM和CSS-DOM。

青春木鱼的博客 2468

第3.4章 机器人第三方库实战总结(四):G2O优化库从入门到实战(附SLAM实例代码)

自定义边同样是满足复杂应用需求的重要手段。自定义边时,需要明确边所连接的顶点类型以及边所表示的误差项的计算方式。假设我们要定义一条边,用于约束两个上述自定义顶点之间的相对位姿和传感器偏移量关系。我们可以这样定义边类:public:// 计算误差// 计算雅可比矩阵// 读盘和存盘函数,这里暂不实现。

行知SLAM 358

AI应用架构师实战:超算中AI与量子计算融合的初探与架构

当大模型的算力需求突破E级超算的极限,当量子计算的“量子优势”从实验室走向真实场景,超算+AI+量子计算的融合架构成为解决复杂问题的关键路径。本文从架构师的实战视角出发,系统拆解三者融合的底层逻辑:从“计算本质”的第一性原理推导,到“量子-经典异构”的架构设计;从“量子机器学习”的代码实现,到“金融/医药”的场景落地。我们将回答:如何用超算支撑量子计算的噪声抑制与纠错?如何用量子计算加速AI模型的训练与推理?如何设计可扩展、高可用的融合系统?最终给出架构师的实战指南——从技术选型到运营管理的全流程方法论。

AIGC应用创新大全的博客 924

SuperColumn TMD到底是什么?Cassandra数据模型介绍(一)

SuperColumn TMD到底是什么?Cassandra数据模型介绍 (一) Translated by leo zheng 原文地址:WTF is a SuperColumn? An Intro to the Cassandra Data Model   By  Arin Sarkissian Digg           过去一两个月,Digg的工程师团队花费了大量...

求鱼不如求渔 691

华为OD机试新系统真题【计算电动车续航里程】

华为OD机试 新系统真题【计算电动车续航里程】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【计算电动车续航里程】多语言题解。

qq_45776114的博客 781
上一篇: 一文说清楚ThreadLocal
下一篇: 为啥春节抢红包总不是运气王?看完微信抢红包算法你就明白了
superjava_
博客等级 码龄5年 254粉丝 81原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值