当前位置: 首页 > news >正文

看懂Using where

1.什么是Using where

在 MySQL 的EXPLAIN执行计划中,Extra列显示Using where是一个非常常见的信息。

简单来说,它的意思是:MySQL 服务器(Server 层)收到存储引擎(Storage Engine 层)返回的数据后,还需要再次根据WHERE条件进行一次数据的筛选(过滤)。

要彻底理解它,我们需要先看一眼 MySQL 的内部架构,以及它跟“有没有走索引”的区别。

1. 核心原理:Server 层与存储引擎的交互

MySQL 内部大致分为两层:

  • Server 层:负责 SQL 解析、优化、执行逻辑,以及最终的数据过滤。

  • 存储引擎层(如 InnoDB):负责真正去磁盘或内存里读写数据。

当出现Using where时,数据的处理流程通常是这样的:

  1. 存储引擎把数据捞出来(可能是全表扫描的一行行数据,也可能是通过索引查到的多条数据)。

  2. 存储引擎把这些数据交还给Server 层

  3. Server 层拿着你的WHERE条件,对这些数据进行逐一比对,把不符合条件的丢弃掉,留下符合条件的返回给客户端。

2. 常见场景分析

很多人误以为“只要写了WHERE子句就一定会显示Using where”,这是错误的。只有当存储引擎无法一次性完美解决所有过滤条件,不得不让 Server 层擦屁股时,才会显示Using where

以下是几种典型场景:

场景 A:完全没走索引(全表扫描)
-- 假设 age 字段没有建任何索引 SELECT * FROM user WHERE age = 18;
  • 执行过程:存储引擎只能进行全表扫描(type = ALL),把整张表的所有数据都读出来,一条一条丢给 Server 层。Server 层通过WHERE age = 18进行筛选。

  • 结果:Extra会显示Using where

场景 B:走了索引,但还有其他无法用索引过滤的条件
-- 假设 name 字段有索引,但 age 字段没有索引 SELECT * FROM user WHERE name = '张三' AND age = 18;
  • 执行过程:存储引擎通过name索引,定位到所有叫“张三”的人的数据行(假设有 100 条),然后把这 100 条数据交给 Server 层。Server 层再通过WHERE age = 18过滤掉不符合年龄的人。

  • 结果:type = ref(走了索引),同时Extra显示Using where(Server 层进行了二次过滤)。

反例:什么时候写了WHERE却不显示Using where
-- 假设 id 是主键 SELECT * FROM user WHERE id = 10;
  • 执行过程:存储引擎通过主键索引,精准地只拿到了id = 10的这一行数据。既然存储引擎返回的数据百分之百就是最终结果,Server 层就不需要再做任何过滤了。

  • 结果:Extra栏是空白(NULL),不会显示Using where

3.Using where是好是坏?需要优化吗?

Using where本身只是一个状态陈述,它无所谓好坏,关键要看它和谁组合

  • 性能很差 🚨:type: ALL+Extra: Using where

    • 含义:全表扫描加服务器端过滤。说明表数据量大时会非常慢,必须优化(通常是给WHERE后面的字段建索引)。

  • 性能尚可/正常 ⚖️:type: ref/range+Extra: Using where

    • 含义:走了索引范围查询,但 Server 层做了二次过滤。如果过滤掉的数据量很少,性能通常没问题;如果过滤掉的数据量极大(比如索引查出 10 万条,Server 过滤后只剩 1 条),说明索引区分度不够,可以考虑建立联合索引来让存储引擎一步到位。

总结口诀

Using where意味着:存储引擎给得太多了,Server 层不得不亲自动手筛选。

2.为什么主键的range也会触发Using where

这是一个极其经典且容易让人产生“索引焦虑”的问题。很多开发者一看到Using where就觉得是不是索引失效了,特别是当WHERE条件明明是主键范围(比如id > 10)时。

结论先行:完全正常,不需要任何优化!主键范围查询(type: range)时出现Using where,是因为MySQL 的架构分工决定的。

底层原因:Server 层要对边界进行“把控”

还记得我们前面提到的 MySQL 双层架构吗?

  • 存储引擎层(InnoDB):负责根据主键的 B+ 树,快速定位到范围的起点(比如id = 11),然后开始顺着叶子节点的双向链表,一条一条地向后读取数据。

  • Server 层:负责逻辑控制。

当你执行类似SELECT * FROM user WHERE id > 10 AND id < 20的范围查询时,底层是这样互动的:

  1. 引擎层找到了id = 11的行,传给 Server 层。

  2. Server 层拿到这行数据,看了一眼你的WHERE条件,发现11 < 20符合要求,于是收下。

  3. 引擎层继续读下一条id = 12传给 Server 层……直到读到id = 20传给 Server 层。

  4. Server 层一比对,发现20 < 20不成立,于是叫停引擎:“行了,别读了,范围到头了。”

💡核心点就在这里:> 只要在执行过程中,Server 层亲自参与了对数据进行WHERE条件的评估、比对或边界控制,执行计划的Extra列就一定会打上Using where的标记。

为什么主键等值查询(id = 1)就没有Using where

你可能会问:“那为什么写WHERE id = 1的时候,Extra 就是空白(NULL),没有Using where呢?”

  • WHERE id = 1type: const):MySQL 的优化器非常聪明。在真正执行 SQL 之前(优化阶段),它就已经知道主键是唯一的,id = 1顶多只有一条数据。所以它直接去引擎层把这一条数据抓上来,当成一个“常量(const)”直接用。

    既然执行期间不需要再进行任何行与行之间的循环比对和边界判断,Server 层就不用挨个评估WHERE条件,自然就没有Using where

  • WHERE id > 10type: range):这是一个流式、循环的过程。引擎层并不知道什么时候该停下来,必须由 Server 层在每一次循环中拿着WHERE条件去把控边界。

对比总结

我们可以通过下表来看清它们的本质区别:

查询场景type 类型Extra 提示实际含义
WHERE id = 1const空白 (NULL)一步到位查到唯一行,Server 层无需循环评估条件。
WHERE id > 10rangeUsing where走了主键索引范围扫描,Server 层在循环接收数据并控制边界。(非常高效,正常现象)

WHERE age = 18

(age无索引)

ALLUsing where没走索引(全表扫描),Server 层把整张表的数据挨个过滤了一遍。(性能很差,需要优化)

💡 铁律

判断一个查询快不快,优先看type列,而不是被Using where吓退。只要typerangekeyPRIMARY,就说明你的主键索引正在全力以赴、极其高效地工作着!

3.为什么主键不走索引下推?

结论非常明确:不能。主键索引(聚簇索引)完全无法使用索引下推(ICP)。

MySQL 官方文档中明确指出:ICP 适用于二级索引(Secondary Index),不适用于聚簇索引(Clustered Index)。在 InnoDB 中,主键索引就是聚簇索引。

为什么主键不需要、也无法使用索引下推?我们可以从它的“核心目的”和“物理结构”来拆解。

1. 核心原因:索引下推的 KPI 是“减少回表”

我们在前面聊过,索引下推(ICP)诞生唯一的目的,就是为了让存储引擎在二级索引树上提前过滤,从而“减少回表(去主键树查数据)的次数”

  • 二级索引:叶子节点只有“索引列 + 主键值”。如果不下推,引擎层得把数据一条条拿去回表,传给 Server 层;如果下推了,引擎层自己在二级索引树上查完,过滤掉不符合的,省去了大量的回表开销。

  • 主键索引:它的叶子节点本身就存放了整张表、最完整的行数据。既然引擎层在扫主键树的时候,手里已经拿到这一行的全部字段了,它就不需要去别的地方“回表”查数据。

既然根本没有“回表”这个动作,索引下推自然就毫无用武之地了。

2. 那么,主键范围查询时引擎层是怎么做的?

既然主键不能走索引下推,那像WHERE id > 10 AND id < 20这样的查询,引擎层是怎么工作的呢?

它会直接利用主键的 B+ 树:

  1. 引擎层快速定位到id = 11的数据页。

  2. 引擎层开始沿着叶子节点的双向链表,顺藤摸瓜,把整行整行的数据直接读出来,源源不断地送给 Server 层。

  3. Server 层在上面接着,一条条比对,直到发现id = 20超过了边界,宣告结束。

在这个过程中,虽然没有索引下推,但由于主键索引本身就是“一步到位”的(不需要二次寻址),它的执行效率依然是所有查询方式里最高的一种。

总结

我们可以用一句话彻底理清它们的关系:

索引下推(ICP)是专门给二级索引打的“补丁”,用来弥补二级索引数据不全、频繁回表的缺陷;而主键索引天生就拥有全量数据,不需要这个补丁。

http://www.rkmt.cn/news/1418407.html

相关文章:

  • Spring Boot项目里RestTemplate调用国外HTTPS接口总失败?别急着改证书,先检查这个配置
  • 大学生学AI,别只聊天!手把手教你搭第一个智能体,惊艳面试官
  • 从AD8421到AD9226:手把手教你搭建一个完整的正弦波信号采集电路(含保护电路设计)
  • 别再手动拖拽了!Fluent中Camera参数详解与视角精准复现指南
  • CesiumHeatmap:三维空间热力图的终极实现方案
  • 2026年05月28日最热门的开源项目(Github)
  • 从一道考研真题的三种错解,聊聊函数极值与最值那些容易踩的坑
  • 别再只会用Edit框了!Simulink封装对话框的10种高级控件(滑块、刻度盘、查找表)全解析
  • 2026年5月28日笔记
  • 从零配置Claude自动修Bug:6步打造全自动开发流程
  • LabVIEW也能玩转YOLOv8实时检测?保姆级TensorRT部署教程(附避坑指南)
  • 2026 年 5 月社工备考指南:考前冲刺题 APP 实测对比 - 讲清楚了
  • 2026年当前,全国知名的徐百慧代言服务商深度解析与选择指南 - 2026年企业资讯
  • Arduino CNC Shield V3硬件改造:实现步进电机独立使能与单电源供电
  • Mac误删文件怎么找回?v6.2 Disk Drill 数据恢复方案
  • GEO优化效果跃升:利用本地评价与社交媒体互动的秘诀
  • 从ADSL到光纤:家庭宽带升级史,以及那些被遗忘的HFC和xDSL技术
  • 一文看懂:智能工厂3DGS数字孪生构建全流程
  • 2026年,揭秘漫剧平台背后的源头厂家真相
  • 019、合成数据生成:3D 渲染、GAN 生成缺陷图片补充工业检测数据集
  • 告别熬夜做图写文案,电商人的“超级助理”已上线
  • 别再死记公式了!用Python可视化带你直观理解CNN感受野的计算过程
  • Joy-Con Toolkit技术方案:Switch手柄通信协议逆向与硬件级定制解决方案
  • ESXi 7.0安装后必做的5件事:从配置管理网络到安全登录,告别裸奔
  • macOS Xbox手柄驱动架构解析与高级应用指南
  • Adobe Acrobat Pro 2023下载安装教程(附安装包)2026最新版(Pro DC 2023)
  • 从理论到实战:一份给数据科学家的nDCG指标使用指南(含Python/Sklearn/真实案例)
  • 2026年第二季度业内推荐:评价高的轮胎撕碎机订购厂家深度解析 - 2026年企业资讯
  • FPGA加速的连续归一化流在LHC实时异常检测中的应用
  • 2026 年 5 月基金从业备考指南:在线刷题与章节练习实测对比 - 讲清楚了