application.yml
注意: url后面必须加上 rewriteBatchedStatements=true 才能开启batch模式
# 数据源配置
spring:
datasource:
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&rewriteBatchedStatements=true
username: root
password: 1511
type: org.springframework.jdbc.datasource.DriverManagerDataSource
mybatis:
type-aliases-package: com.dzw.domain
mapper-locations: classpath*:mapper
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for text
-- ----------------------------
DROP TABLE IF EXISTS `text`;
CREATE TABLE `text` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
`name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
`sex` tinyint(4) NULL DEFAULT NULL,
`text` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 91008 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS = 1;
测试数据: 10000条数据插入时间对比
1.batch模式
@Autowired
private SqlSessionFactory sqlSessionFactory;
@Test
void contextLoads() {
//批量处理效率
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); //批处理模式
TextMapper mapper = sqlSession.getMapper(TextMapper.class);
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
Text text = new Text();
text.setName(String.valueOf(i));
text.setSex(1);
text.setText(String.valueOf(i));
mapper.insert(text);
}
sqlSession.flushStatements();
System.out.println(System.currentTimeMillis()-start); // 885 860 853
}
2.foreach模式
@Autowired
private TextService textService;
@Test
void insertFor() {
//foreach标签批量处理效率
long start = System.currentTimeMillis();
ArrayList texts = new ArrayList<>();
for (int i = 0; i < 10000; i++) {
Text text = new Text();
text.setName(String.valueOf(i));
text.setSex(1);
text.setText(String.valueOf(i));
texts.add(text);
if(texts.size()>=10000){
textService.insertFor(texts);
texts.clear();
}
}
System.out.println(System.currentTimeMillis()-start);
}
3.总结
### mybatis batch模式和foreach标签 进行批量插入操作时 ,耗时对比
batch 三次插入1w条数据耗时
885 860 853 平均:866
foreach 三次插入1w条数据耗时
500 1313 1288 平均:1292
2000 -> 1096 1052 1091 平均:1079
10000 -> 1032 1006 973 平均:1003
注意: 由于foreach时拼接sql数据,该方法会存在语句长度限制,有可能会抛出Could not execute JDBC batch update异常
my.ini中修改以下配置
max_allowed_packet=1M
net_buffer_length=2K
对比:
1292/866 = 1.49
batch插入速度比foreach要快很多。
结论: foreach标签对比batch模式 效率慢了0.5,java代码进行for循环批量插入就不测试了,肯定要慢几十倍
我在网上看了很多文章,都是foreach效率比batch高,可能时jdbc url没加上 rewriteBatchedStatements=true的原因,如有错误请各位斧正。



