最近广东快乐十分源码下载联系方式:QQ:2747044651【征途源码论坛http://t.cn/Eyb4XkK】
\"在这里插入图片描述\"
\"在这里插入图片描述\"
\"在这里插入图片描述\"在做一个类似于综合报表之类的东西,需要查询所有的记录(数据库记录有限制),大概有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
@AllArgsConstructor
public 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=1 and id in #{item} 3. 执行 main 方法:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { “classpath:spring-mybatis. ” })
public class MainTest {

@Autowired
private IPersonService personService;

@Test
public void test(){
    // 构造 1W 个 ID
    List<Integer> ids = new ArrayList<>();
    for (int i = 1; i <= 10000; i++) {
        ids.add(i);
    }
    long start = System.currentTimeMillis();
    
    // 执行三次
    personService.queryPersonByIds(ids);
    personService.queryPersonByIds(ids);
    personService.queryPersonByIds(ids);

    long end = System.currentTimeMillis();
    System.out.println(String.format(\"耗时:%d\", end - start));
}

}
结果:耗时:2853
可以看到通过 foreach 的方法,大概需要 3s

方式二
在代码中封装 SQL ,在配置文件中 通过 ${xxx} 来获取:

  1. 在 dao 添加方法:

List queryPersonByIds2(@Param(“ids”) String ids);
2. 配置文件SQL:

select * from person where 1=1 and id in ${ids} 3. 执行 main 方法:

@Test
public void test_3(){
// 拼接 SQL
StringBuffer sb = new StringBuffer();
sb.append(\"(\");
for (int i = 1; i < 10000; i++) {
sb.append(i).append(\",\");
}
sb.deleteCharAt(sb.toString().length() - 1);
sb.append(\")\");
// 最终的 SQL 为 (1,2,3,4,5…)

long start2 = System.currentTimeMillis();

// 执行三次
personService.queryPersonByIds2(sb.toString());
personService.queryPersonByIds2(sb.toString());
personService.queryPersonByIds2(sb.toString());

long end2 = System.currentTimeMillis();
System.out.println(String.format(\"耗时:%d\", end2 - start2));

}
结果:耗时:360
通过拼接 SQL,使用 ${xxx} 的方式,执行同样的 SQL ,耗时大概 360 ms

方式三
在代码中封装 SQL ,在配置文件中 通过 #{xxx} 来获取:

  1. 在 dao 中添加方法:

List queryPersonByIds3(@Param(“ids”) String ids);
2. 配置文件SQL:

select * from person where 1=1 and id in (#{ids}) 3. 执行 main 方法:

@Test

收藏 打印