mysql WHERE条件本质是什么_mysql集合筛选原理

来源:这里教程网 时间:2026-02-28 20:53:06 作者:

WHERE 条件本质是逐行逻辑判断

MySQL 的

WHERE
不是“提前过滤”或“智能索引跳过”,而是对
FROM
产出的每一行记录,执行一次布尔表达式求值:真 → 留下,假或
NULL
→ 舍弃。这个过程发生在 SELECT 列计算、别名(
AS
)和排序(
ORDER BY
)之前,所以你不能在
WHERE
里引用
SELECT
中定义的别名(比如
WHERE total > 100
报错,因为
total
还没生成)。

WHERE salary + bonus > 5000
:每行都实时算一次加法,再比大小
WHERE name LIKE 'Li%'
:对每行
name
值做字符串匹配,不是查字典树
WHERE updated_at >= '2025-01-01'
:时间字段不走索引?那它就老老实实扫全表每行比时间

集合筛选 ≠ 数学集合运算,而是带语义的行级过滤

别被“集合”这个词误导——MySQL 没有把表当数学集合去交/并/差。所谓“筛选出满足条件的集合”,实际是:扫描原始数据集(可能是全表、索引覆盖扫描、或分区子集),对每条记录运行

WHERE
表达式,收集所有返回
TRUE
的行,拼成结果集。它不保证顺序、不自动去重(除非加
DISTINCT
),也不关心行之间是否“属于同一逻辑组”。

没有隐含的
GROUP BY
或唯一性约束
WHERE id IN (1,2,3)
WHERE id = 1 OR id = 2 OR id = 3
语义等价,但执行计划可能不同(尤其有索引时)
WHERE status != 'done'
会漏掉
status IS NULL
的行——因为
NULL != 'done'
结果是
NULL
,不是
TRUE

最容易踩的三个坑

这些不是语法错误,而是逻辑陷阱,线上查不到数据时八成栽在这儿:

空值陷阱:用
=
!=
>
判断
NULL
全部失效,必须显式写
IS NULL
IS NOT NULL
LIKE 开头通配符
WHERE name LIKE '%ing'
无法使用 B+ 树索引的最左前缀,大概率触发全表扫描
隐式类型转换:比如
WHERE mobile = 13812345678
(字段是
VARCHAR
),MySQL 会把字符串转数字再比,可能引发索引失效或意外匹配(如
'13812345678abc'
也被转成
13812345678

性能真相:WHERE 本身不慢,慢的是没走索引的逐行判断

WHERE
子句的执行成本,几乎完全取决于它能否利用索引快速定位(Index Seek),而不是靠 CPU 算得快。一旦变成全表扫描(
type: ALL
),哪怕条件再简单(
WHERE 1=1
),数据量大了照样卡。

建索引前先看
EXPLAIN SELECT ... WHERE ...
key
rows
字段
复合索引要注意字段顺序:
INDEX(status, created_at)
能加速
WHERE status = 'active' AND created_at > '2025-01-01'
,但对
WHERE created_at > '2025-01-01'
无效
WHERE JSON_CONTAINS(info, '"admin"', '$.roles')
这类函数条件,基本告别索引(除非建函数索引且 MySQL ≥ 8.0.13)
真正决定 WHERE 效率的,从来不是条件写得多漂亮,而是数据库能不能“跳着读”,而不是“从头读到尾”。

相关推荐