背景
最近在做一个类似于综合报表之类的东西,需要查询所有的记录(数据库记录有限制),大概有1W条记录,该报表需要三个表的数据,也就是根据这 1W 个 ID 去执行查询三次数据库,其中,有一条查询 SQL 是自己写,其他两条是根据别人提供的接口进行查询,刚开始的时候,没有多想,直接使用 in 进行查询,使用 Mybatis 的 foreach 语句;项目中使用的是 jsonrpc 来请求数据,在测试的时候,发现老是请求不到数据,日志抛出的是 jsonrpc 超时异常,继续查看日志发现,是被阻塞在上面的三条SQL查询中。
在以前分析 Mybatis 的源码的时候,了解到,Mybatis 的 foreach 会有性能问题,所以改了下 SQL,直接在代码中拼接SQL,然后在 Mybatis 中直接使用 # 来获取,替换 class 测试了下,果然一下子就能查询出数据。
前提
这里先不考虑使用 in 好不好,如何去优化 in,如何使用 exists 或 inner join 进行代替等,这里就只是考虑使用了 in 语句,且使用了 Mybatis 的 foreach 语句进行优化,其实 foreach 的优化很简单,就是把 in 后面的语句在代码里面拼接好,在配置文件中直接通过 #{xxx} 或 ${xxx} 当作字符串直接使用即可。
测试
在分析 foreach 源码之前,先构造个数据来看看它们的区别有多大。
建表语句:
CREATE TABLE person( id int(11) PRIMARY KEY NOT NULL, name varchar(50), age int(11), job varchar(50));
插入 1W 条数据:
POJO 类:
@Getter@Setter@ToString@NoArgsConstructor@AllArgsConstructorpublic class Person implements Serializable { private int id; private String name; private String job; private int age;}
方式一
通过原始的方式,使用 foreach 语句:
1. 在 dao 里面定义方法:
List queryPersonByIds(@Param("ids") List ids);
2. 配置文件SQL:
select * from person where 1=1and id in