目标
最近,在项目中使用MyBatis进行SQL脚本编写时,我遇到了以“WHERE 1=1”开头的WHERE子句的做法,以简化多个条件的串联。这里有一个例子来讨论这种技术以及“WHERE 1=1”是否对性能有任何影响。
<select id="" parameterType="">SELECT * FROM users WHERE 1=1<if test="userName != null">AND user_name = #{userName}</if><if test="userAge != null">AND user_age = #{userAge}</if><if test="userSex != null">AND user_sex = #{userSex}</if>
</select>
讨论MyBatis中连接条件的两种常见做法
1、第一种where
<select id="" parameterType="">SELECT * FROM users WHERE 1=1<if test="userName != null">AND user_name = #{userName}</if><if test="userAge != null">AND user_age = #{userAge}</if><if test="userSex != null">AND user_sex = #{userSex}</if>
</select>
2、第二种
MyBatis 提供了一个 标记,仅当至少有一个条件计算结果为 true 时,该标记才会插入 WHERE 子句。如果 AND 或 OR 之前没有有效的语句,则 元素将删除它们。
<select id="" parameterType="">SELECT * FROM users <where><if test="userName != null">AND user_name = #{userName}</if><if test="userAge != null">AND user_age = #{userAge}</if><if test="userSex != null">AND user_sex = #{userSex}</if></where>
</select>
性能影响
使用“WHERE 1=1”和 标签的性能差异在于前者对SQL查询性能的优化,而后者则在于动态生成SQL语句。我们来详细分析一下:
1、mysql版本
SELECT VERSION(); -- 5.7.44
插入数据:
CREATE TABLE IF NOT EXISTS users
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'Auto-increment ID',name VARCHAR(20) COMMENT 'Name',age TINYINT COMMENT 'Age'
) ENGINE = INNODB;INSERT INTO users (name, age) VALUES ('John', 18), ('Jane', 19), ('Doe', 20), ('Smith', 21);
在5.7以上版本中,SQL查询优化将消除“1=1”部分,不影响索引。不过值得注意的是,较低版本可能会受到一些影响,值得关注。
EXPLAIN SELECT * FROM users WHERE 1=1 AND name = 'John';
SHOW WARNINGS;
优化后的 SQL 表明“1=1”部分已被查询优化器优化掉,因此不会显着影响整体性能。
性能比较
– With “WHERE 1=1” AND a condition
SELECT * FROM users WHERE 1=1 AND name = ‘John’;
– Execution Time: 0.046s
– With just “WHERE 1=1”
SELECT * FROM users WHERE 1=1;
– Execution Time: 0.046s
与由 MySQL 服务器的查询优化器处理的“WHERE 1=1”相比, 标签处理动态 SQL 构造。然而,它不会显着影响性能,因为底层动态 SQL 生成并不太复杂。
结论
where 1=1 和 标记都是连接条件的常见做法,对性能没有重大影响。他们之间的选择可以基于团队标准。此外,这些方法的性能不受处理的数据量的影响,因为每次执行仅处理一次,因此即使对于大型数据集,也不存在性能差异。