MySQL 5.7+ 中 WHERE 1=1 不影响性能,因其在解析→重写→优化阶段被常量折叠优化自动移除,执行计划等同于无该条件的SQL,EXPLAIN与SHOW WARNINGS可验证优化后语句已剔除1=1。
MySQL 5.7+ 中 WHERE 1=1 不影响执行性能
它会被查询优化器在解析阶段直接移除,不参与执行计划生成。运行 explain select * from user where 1=1 and name = 'tom' 后再执行 show warnings,能看到优化后的语句就是 select * from user where (name = 'tom')。这个过程发生在“解析 → 重写 → 优化”阶段,和存储引擎、索引是否存在都无关。
Navicat 里测出耗时差异,大概率不是 1=1 的锅
Navicat 自带的执行时间统计(比如信息选项卡底部显示的 0.004 秒)容易受干扰,常见干扰源包括:
- 查询缓存未禁用(
SQL_NO_CACHE没加,旧版本 MySQL 可能命中缓存) - 两次执行走的是不同执行路径:一次用了索引,另一次因隐式类型转换或函数包裹(如
UPPER(name))导致索引失效 - 动态拼接时漏判空值,实际执行了
AND age = NULL这类无效条件,查不到结果但没报错 - Navicat 自身连接池复用或预热状态不同,尤其在刚启动或切换连接后
真正该盯住的是拼接逻辑本身
WHERE 1=1 是个信号灯——它出现的地方,往往意味着 SQL 是手拼的、缺乏结构约束。容易被忽略的实际问题有:
- 参数未校验:比如
if (name != null)没覆盖""或空白字符串,拼出AND name = ''导致全表扫 - 类型错位:数字字段拼成字符串(
"AND id = '" + userId + "'"),触发隐式转换,索引失效 - 重复追加:循环拼接时没清空 StringBuilder,同一条件被加了两遍
- SQL 注入风险:直接字符串拼接且未用预编译参数(尤其在 Navicat 手动测试时临时改 SQL)
MyBatis 场景下优先用 <where> 标签
Navicat 常用于调试 MyBatis 生成的 SQL,这时要注意:WHERE 1=1 是纯 SQL 层 hack,而 <where> 是框架层语义化处理:
-
<where>会自动剔除开头多余的AND,生成的 SQL 更干净,EXPLAIN看到的就是真实条件 -
WHERE 1=1在<if>全为空时仍会留下WHERE 1=1,虽能执行但语义冗余,还可能掩盖拼接 bug - Navicat 中复制粘贴这类 SQL 调试时,
<where>生成的语句更易读、更少歧义
真正拖慢查询的从来不是 1=1 这三个字符,而是它背后裸露出来的拼接随意性——比如一个没加引号的字符串参数,或一个没判空的数字字段,这些在 Navicat 里一眼看不出,却让执行计划彻底跑偏。



















