前言
最近刷到了一篇文章,里面提到:“ WHERE 1=1 会影响 SQL 的执行效率,甚至可能造成索引失效。”虽然我本人也一般不使用
1=1
这个条件,但是我很好奇为什么会使索引失效。因此,我查阅了相关资料,并进行了测试。本文将总结一下关于WHERE 1=1
的讨论并用 SQL 测试来验证实际影响。
1. 什么是 WHERE 1=1
WHERE 1=1
是一种常见的 SQL 编写习惯,通常用于构造动态查询。例如:
SELECT * FROM table_name WHERE 1=1
AND column1 = 'value1'
AND column2 = 'value2';
1=1
始终为真,它的作用是简化动态查询条件的拼接。开发者可以在需要时随时添加 AND
条件,而无需额外处理首个条件的逻辑。
2. 争议点
有人认为 WHERE 1=1
可能影响 SQL 的执行效率,甚至导致索引失效。这主要是因为:
1=1
是冗余条件,可能会让查询优化器生成不必要的执行计划。- 当查询优化器无法完全消除冗余条件时,可能会导致性能下降或索引未被正确使用。
为了验证这些观点,我设计了以下测试。
3. 测试准备
3.1 创建测试表
-- 创建表结构
CREATE TABLE table1 (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
table2_id INT,
INDEX idx_table2_id (table2_id)
);
CREATE TABLE table2 (
id INT PRIMARY KEY AUTO_INCREMENT,
description VARCHAR(255),
table3_id INT,
INDEX idx_table3_id (table3_id)
);
CREATE TABLE table3 (
id INT PRIMARY KEY AUTO_INCREMENT,
category VARCHAR(100),
table4_id INT,
INDEX idx_table4_id (table4_id)
);
CREATE TABLE table4 (
id INT PRIMARY KEY AUTO_INCREMENT,
tag VARCHAR(100),
table5_id INT,
INDEX idx_table5_id (table5_id)
);
CREATE TABLE table5 (
id INT PRIMARY KEY AUTO_INCREMENT,
value INT,
status VARCHAR(50)
);
3.2 每张表随机生成100w数据
3.3 确认数据是否生成成功
SELECT 'table1' AS table_name, COUNT(*) AS row_count FROM table1
UNION ALL
SELECT 'table2' AS table_name, COUNT(*) AS row_count FROM table2
UNION ALL
SELECT 'table3' AS table_name, COUNT(*) AS row_count FROM table3
UNION ALL
SELECT 'table4' AS table_name, COUNT(*) AS row_count FROM table4
UNION ALL
SELECT 'table5' AS table_name, COUNT(*) AS row_count FROM table5;
3.4 测试查询
3.4.1 使用 WHERE 1=1
EXPLAIN SELECT
t1.id AS table1_id,
t1.name AS table1_name,
t2.description AS table2_description,
t3.category AS table3_category,
t4.tag AS table4_tag,
t5.value AS table5_value,
t5.status AS table5_status
FROM
table1 t1
JOIN table2 t2 ON t1.table2_id = t2.id
JOIN table3 t3 ON t2.table3_id = t3.id
JOIN table4 t4 ON t3.table4_id = t4.id
JOIN table5 t5 ON t4.table5_id = t5.id
WHERE 1=1
AND t1.name LIKE 'A%'
AND t2.description = 'Desc1'
AND t3.category IN ('Category1', 'Category2')
AND t4.tag = 'Tag1'
AND t5.value > 50
AND t5.status = 'Active';
3.4.2 不使用 WHERE 1=1
EXPLAIN SELECT
t1.id AS table1_id,
t1.name AS table1_name,
t2.description AS table2_description,
t3.category AS table3_category,
t4.tag AS table4_tag,
t5.value AS table5_value,
t5.status AS table5_status
FROM
table1 t1
JOIN table2 t2 ON t1.table2_id = t2.id
JOIN table3 t3 ON t2.table3_id = t3.id
JOIN table4 t4 ON t3.table4_id = t4.id
JOIN table5 t5 ON t4.table5_id = t5.id
WHERE t1.name LIKE 'A%'
AND t2.description = 'Desc1'
AND t3.category IN ('Category1', 'Category2')
AND t4.tag = 'Tag1'
AND t5.value > 50
AND t5.status = 'Active';
4. 测试结果
通过对比两种查询的 EXPLAIN
输出可以发现:
- 可以看出在
MySQL5.7+
的版本,查询优化器能够自动忽略1=1
条件,因此不会对性能造成显著影响。 - 索引是否被使用取决于查询条件和数据分布,与是否包含
1=1
无直接关系。
5. 总结
类别 | 优点 | 缺点 |
---|---|---|
简化动态 SQL 语句拼接 | - 动态条件拼接时简洁直观,避免复杂逻辑判断。 - 直接追加 AND 条件,无需单独判断 WHERE 是否存在。 |
- 对于静态查询, 1=1 显得冗余,违背简洁性原则。 |
提高代码可读性与一致性 | - 使用固定模式让代码结构更统一,便于阅读。 | - 过度依赖 1=1 可能导致代码冗余,即使在不需要动态拼接时仍被使用。 |
动态查询工具集成 | - 在框架(如 MyBatis、ORM 工具)中无需单独处理首个条件,便于多条件动态生成。 | - 某些老旧版本数据库可能无法完全忽略 1=1 ,增加不必要的优化器负担。 |
性能影响 | - 现代数据库优化器会忽略冗余条件,对性能几乎没有影响。 | - 在极高性能要求场景中,减少冗余条件可能带来微小优化。 |
适用场景 | - 适用于动态查询和条件复杂的 SQL 生成场景。 | - 对于简单、固定的静态查询,使用 1=1 会显得多余。 |
额外逻辑 | - 对复杂查询条件切换时, 1=1 可以减少判断逻辑,保持查询生成代码清晰。 |
- 在部分系统中(高性能要求或老旧版本数据库),可能会出现额外的计划生成开销。 |
WHERE 1=1
本质上是为了简化动态 SQL的编写,其对性能的影响微乎其微。在现代数据库中,查询优化器足够智能,可以忽略此类冗余条件。不过,在高性能场景中,避免冗余代码依然是良好的编程习惯。
“如果此文章对您有帮助💪,帮我点个赞👍,感激不尽🤝!”