SQL语句`WHERE 1=1`,到底会不会影响性能?

前言

最近刷到了一篇文章,里面提到:“ 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=1 是冗余条件,可能会让查询优化器生成不必要的执行计划。
  2. 当查询优化器无法完全消除冗余条件时,可能会导致性能下降或索引未被正确使用。

为了验证这些观点,我设计了以下测试。

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数据

image

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;

image

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';

image

image

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';

image

image

4. 测试结果

通过对比两种查询的 EXPLAIN 输出可以发现:

  1. 可以看出在 MySQL5.7+ 的版本,查询优化器能够自动忽略 1=1 条件,因此不会对性能造成显著影响。
  2. 索引是否被使用取决于查询条件和数据分布,与是否包含 1=1 无直接关系。

5. 总结

类别 优点 缺点
简化动态 SQL 语句拼接 - 动态条件拼接时简洁直观,避免复杂逻辑判断。
- 直接追加 AND 条件,无需单独判断 WHERE 是否存在。
- 对于静态查询, 1=1 显得冗余,违背简洁性原则。
提高代码可读性与一致性 - 使用固定模式让代码结构更统一,便于阅读。 - 过度依赖 1=1 可能导致代码冗余,即使在不需要动态拼接时仍被使用。
动态查询工具集成 - 在框架(如 MyBatis、ORM 工具)中无需单独处理首个条件,便于多条件动态生成。 - 某些老旧版本数据库可能无法完全忽略 1=1,增加不必要的优化器负担。
性能影响 - 现代数据库优化器会忽略冗余条件,对性能几乎没有影响。 - 在极高性能要求场景中,减少冗余条件可能带来微小优化。
适用场景 - 适用于动态查询和条件复杂的 SQL 生成场景。 - 对于简单、固定的静态查询,使用 1=1 会显得多余。
额外逻辑 - 对复杂查询条件切换时, 1=1 可以减少判断逻辑,保持查询生成代码清晰。 - 在部分系统中(高性能要求或老旧版本数据库),可能会出现额外的计划生成开销。

WHERE 1=1 本质上是为了简化动态 SQL的编写,其对性能的影响微乎其微。在现代数据库中,查询优化器足够智能,可以忽略此类冗余条件。不过,在高性能场景中,避免冗余代码依然是良好的编程习惯。

“如果此文章对您有帮助💪,帮我点个赞👍,感激不尽🤝!”