当前位置:首页 > 文章列表 > 数据库 > MySQL > MySQL 多列索引遇到 IS NULL 时如何判断顺序

MySQL 多列索引遇到 IS NULL 时如何判断顺序

来源:17golang原创 2026-09-15 03:33:03 0浏览 收藏

我在给软删除表补索引时,最容易误判的一点就是:看到 deleted_at IS NULL,就以为 NULL 条件必须放在复合索引第一列。实际判断不是看 WHERE 里谁写在前面,而是看索引定义的左前缀、查询是否提供了前面的列,以及 EXPLAIN 显示优化器真正用了哪些列。IS NULL 本身可以参与索引范围,但它不会自动跳过复合索引前面的空缺列。

要点速览
  • 交换 WHERE 中两个条件的书写位置,通常不会改变复合索引的列顺序。
  • (tenant_id, deleted_at, created_at) 中,tenant_id = 7deleted_at IS NULL 可以共同限定索引前缀。
  • 最终以 keyused_key_partskey_length 和访问类型复查,不凭感觉改索引。

WHERE 条件顺序,不等于索引列顺序

假设表里有租户、软删除时间和创建时间:

CREATE TABLE orders (
  id BIGINT PRIMARY KEY,
  tenant_id BIGINT NOT NULL,
  deleted_at DATETIME NULL,
  created_at DATETIME NOT NULL,
  KEY idx_tenant_deleted_created (tenant_id, deleted_at, created_at)
);

下面两条查询只是条件书写顺序不同:

-- 两个条件都指向同一组业务约束,便于对比 WHERE 文本顺序
SELECT id FROM orders
WHERE tenant_id = 7 AND deleted_at IS NULL;

-- 交换书写位置,不代表要交换索引定义
SELECT id FROM orders
WHERE deleted_at IS NULL AND tenant_id = 7;

索引的顺序仍然是 tenant_iddeleted_atcreated_at。优化器会从可形成的索引条件出发,而不是按 SQL 字符串从左到右机械选列。因此不要为了配合第二条写法,就把索引改成 (deleted_at, tenant_id)

IS NULL 在复合索引里到底占哪一段

MySQL 官方手册把 IS NULL 列为可以用于索引和范围搜索的条件。对 B-Tree 多列索引来说,等值比较、IS NULL 都可能让优化器继续考虑后续键列。上面的例子里,tenant_id = 7 先固定第一段,deleted_at IS NULL 再固定第二段;created_at 是否继续参与范围,要看查询是否写了它以及优化器的成本判断。

MySQL 复合索引中 tenant_id 等值条件、deleted_at IS NULL 与索引前缀和范围的关系示意图
图1:MySQL 多列索引关系示意图,查看查询谓词如何对应索引前缀与范围边界。

关键误区在于“只要条件里出现了某个索引列,就能直接用它”。如果索引是 (tenant_id, deleted_at),查询只有 deleted_at IS NULL 时,deleted_at 并不是左前缀。MySQL 可能因为其他优化策略选择不同访问路径,但不能把“列在索引里”当成“必然按这一列定位”。

索引到底该把 deleted_at 放前面吗

没有脱离查询集合的固定答案。先把最常见的三类请求列出来:

查询形态更直接的左前缀判断重点
tenant_id = ?(tenant_id, ...)租户隔离是主要入口
deleted_at IS NULL(deleted_at, ...)是否经常跨租户查未删除数据
tenant_id = ? AND deleted_at IS NULL两种顺序都要实测兼顾单列前缀、数据分布和其他查询

如果业务几乎所有请求都带租户条件,(tenant_id, deleted_at, created_at) 往往更容易覆盖租户内的列表查询;如果确实存在大量只按未删除状态筛选的跨租户任务,才有理由评估 (deleted_at, tenant_id) 或独立索引。这里不建议仅凭 NULL 比较特殊就固定把它放第一列:NULL 占比、租户数量、排序需求和回表成本都会改变选择。

用 EXPLAIN 判断到底用了哪一列

我通常先看计划,再决定是否调整定义。示例只展示检查方法,不代表任意数据集都会返回相同的行数:

-- 用 JSON 计划查看实际使用的索引列,不执行查询本身
EXPLAIN FORMAT=JSON
SELECT id, created_at
FROM orders
WHERE tenant_id = 7
  AND deleted_at IS NULL
  AND created_at >= '2026-01-01';

-- 传统表格输出便于快速比较 key 和 key_len
EXPLAIN SELECT id, created_at
FROM orders
WHERE tenant_id = 7 AND deleted_at IS NULL;

JSON 结果里重点找 keyused_key_parts;传统格式先看 keykey_lenrowsExtrakey 说明选了哪条索引,used_key_parts 说明实际使用到哪些键列,key_len 可以帮助判断使用了多长的复合键前缀。看到索引被选中,不代表每个索引列都参与定位。

MySQL EXPLAIN 输出中 key、used_key_parts、key_length、访问类型和剩余条件的关系示意图
图2:EXPLAIN 证据示意图,沿着索引证据分组查看实际使用的索引前缀。

复查时还要注意统计信息和真实数据分布。若 rows 估算与实际明显不符,可以先确认表结构、索引定义和统计信息是否处于当前状态,再用同一条业务 SQL 比较候选索引。不要用 FORCE INDEX 直接掩盖计划问题,它更适合做有边界的对照实验。

相关问题

deleted_at IS NULL 写在 WHERE 第一行会更快吗?

通常不会。WHERE 的文本顺序不是复合索引定义,是否更快要看最终执行计划和数据分布。

索引被使用了,为什么查询仍然扫描很多行?

可能只使用了索引的前缀,后续条件作为过滤条件处理,也可能 NULL 值占比很高。结合 used_key_partsrows 和实际执行观察。

只查询 deleted_at IS NULL,一定要新建索引吗?

不一定。先确认这类查询是否频繁、结果集是否足够小,以及现有索引是否能覆盖。用 EXPLAIN 和真实业务 SQL 比较后再决定。

一句话收束:IS NULL 可以参与复合索引定位,但索引顺序应由完整查询模式决定;先看左前缀,再看 EXPLAIN,最后才改索引。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
墨刀AI生成原型后怎么交给研发?产品经理要补齐的页面状态和验收备注墨刀AI生成原型后怎么交给研发?产品经理要补齐的页面状态和验收备注
上一篇
墨刀AI生成原型后怎么交给研发?产品经理要补齐的页面状态和验收备注
Redis XCLAIM 重试消息时如何设置 idle 条件
下一篇
Redis XCLAIM 重试消息时如何设置 idle 条件
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    27次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    131次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    63次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    23次使用
  • CMMLU中文大模型评估基准:功能、使用教程与应用场景解析
    CMMLU
    深入了解CMMLU中文评估基准,涵盖67个学科主题,提供数据集下载、Zero-shot/Five-shot评估方法及排行榜,助力优化中文语言模型性能。
    8次使用