Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案 - Go语言中文社区

Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案


Mybatis与JDBC批量插入MySQL数据库性能测试

 

 

Author:boonya

 

Date:2017-04-13

 

1      背景

系统中需要批量生成单据数据到数据库表,所以采用批量插入数据库的方式。由于系统中ORM操作集成使用的是Mybatis来完成的。

 

在Mybatis中操作一般使用批量插入的方式如下:

<insert id="insertBatch" parameterType="java.util.List"  >

     insert into userinfo (uid, uname, uphone, uaddress)

     values

    <foreach collection="list" item="item"index="index" separator=",">

    (#{item.uid,jdbcType=INTEGER},

     #{item.uname,jdbcType=VARCHAR},

     #{item.uphone,jdbcType=VARCHAR},

     #{item.uaddress,jdbcType=VARCHAR}

     )

   </foreach>

   </insert>

在实际生产中发现,这样调用的效率并不高,于是我们迫切地需要寻找一种处理批量插入性能较高的方式——回归原生数据库JDBC操作。我们要分析Mybatis和JDBC的插入性能,来决策适合我们生产系统的批量插入方式。

 

参考资料中有一篇文章是对Spring MybatisSpring JDBC插入效率的测试,由于测试的数据量不多不予置评。

2      Mybatis

2.1  Mybatis测试样本1K

测试10组数据:

时间(ms)                                                                

923

412

426

408

405

353

365

344

316

493

 

2.2  Mybatis测试样本2K

测试10组数据:

时间(ms)                                                                

11031

3340

3571

2327

7273

1353

2676

1249

1245

1155

 

2.3  Mybatis测试样本4K

测试10组数据:

时间(ms)                                                                

6070

5565

5731

5400

5830

5543

5469

5697

5528

5399

 

2.4  Mybatis测试样本6K

测试10组数据:

时间(ms)                                                                 

13383

12672

13030

13484

13841

12952

13331

13275

13000

13236

 

2.5  Mybatis测试样本8K

测试10组数据:

时间(ms)                                                               

25312

24702

27065

25921

25156

24686

25314

33947

25304

25853

 

2.6  Mybatis测试样本10K

测试10组数据:

时间(ms)                                                               

42148

39209

38548

40109

37820

37728

38178

38481

38157

39032

 

2.7  Mybatis测试样本15K

测试10组数据:

时间(ms)                                                              

98250

88585

87438

89547

88427

89522

83261

80842

87163

84804

 

2.8  Mybatis测试样本20K

测试10组数据:

时间(ms)                                                              

145481

146618

147098

145578

144947

145614

142014

142315

141984

143625

 

2.9  性能测试样本平均值

2.9.1  测试样本SQL

2.9.1.1       毫秒级SQL【time(ms)】

-- DELETE FROMprocess_spend_time_result  WHEREpmethod='mybatis';

 

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=1000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=2000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=4000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=6000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=8000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=15000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=20000 AND p.pmethod='mybatis';

2.9.1.2       秒级SQL【time(s)】

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=1000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=2000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=4000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=6000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=8000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=15000 AND p.pmethod='mybatis';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=20000 AND p.pmethod='mybatis';

2.9.2  测试数据汇总

数据4舍5入保留3位小数

测试样例                                       

AVG(s)                                             

1K

0.445

2K

3.522

4K

5.623

6K

13.221

8K

26.326

10K

38.941

15K

87.784

20K

144.527

 

2.10    Mybatis批量插入问题

2.10.1             问题一:处理性能低下

处理10000条耗时:34292ms


2.10.2             问题二:批量处理数据量大小受限

Windows下需要修改MySQL的my.ini文件加入如下配置内容:

max_allowed_packet=500M

Linux下是在/my.cnf修改添加如上内容。

 

也可以直接这样设置:

SET GLOBAL max_allowed_packet=1073741824;

但MySQL重启后就不起作用了。

2.10.3             问题三:线程处理锁表

在通过多线程并发处理的时,很容易导致数据库表锁表,使得后续的操作无法进行。

2.10.4             问题四:导致对象回收GC问题

对象超出GC对象回收阀值,导致程序中断。


3      JDBC

3.1  JDBC测试数据1W

测试10组数据:

 

普通插入(ms)

普通+事务(ms)

普通批量(ms)

批量+事务(MS)

28489

801

31287

3494

30536

3042

35547

1899

25571

2041

31022

3501

27954

2733

28927

2547

29620

1261

34408

1449

27125

819

29318

923

28993

1079

31099

939

27594

2547

33504

3410

27967

781

31646

3587

33145

1293

37030

1912

 

3.2  JDBC测试数据5W

测试10组数据:

 

普通插入(ms)

普通+事务(ms)

普通批量(ms)

批量+事务(MS)

131427

11568

168623

6926

132271

19313

231526

9915

192176

5238

227724

10978

185640

18955

227497

41959

211777

11238

184970

9461

208446

5019

263636

23394

253351

14265

227391

24870

225268

17009

229871

5583

163739

9719

230719

16657

215033

15802

238018

5330

 

3.3  JDBC测试数据10W

测试10组数据:

 

普通插入(ms)

普通+事务(ms)

普通批量(ms)

批量+事务(MS)

308773

21389

360510

16432

352773

23487

372343

25545

378805

24034

368416

12507

384189

30119

392974

23742

369975

30651

378634

26180

368659

11902

416932

21321

388453

12644

411571

18138

391155

11287

396363

11678

368055

30987

399078

12212

363375

22576

361478

18544

 

3.4  JDBC测试数据25W

测试10组数据:

 

普通插入(ms)

普通+事务(ms)

普通批量(ms)

批量+事务(MS)

942067

51343

990800

70103

1070688

28737

1051132

35536

1002076

38065

1222409

89644

1073114

57050

1312620

82354

960697

51733

1338932

33428

1025890

37666

1273338

76934

1017361

50916

1115627

92790

1077821

78650

1175512

52427

1038000

23290

1247797

91801

1200532

75494

1262051

72087

 

3.5  JDBC测试数据50W

测试10组数据:

 

普通插入(ms)

普通+事务(ms)

普通批量(ms)

批量+事务(MS)

1914920

166575

2059826

146472

2111596

62807

1897888

125075

2174029

147265

1891542

166921

1948838

61284

2129791

93167

1909861

167575

1856811

56286

1990816

141381

1980060

148012

1896793

48087

2065937

56832

2130856

174388

2019914

113289

2073636

117462

2045715

102792

1966828

141319

1857867

116854

 

3.6  JDBC测试样本均值

3.6.1  测试样本SQL

3.6.1.1       毫秒级SQL【time(ms)】

 

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsertWithTransaction2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsertWithTransaction2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=100000 and p.pmethod='batchInsertWithTransaction2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=250000 and p.pmethod='batchInsertWithTransaction2';

SELECTAVG(p.ptime) FROM process_spend_time_resultp WHEREp.plimit=500000 andp.pmethod='batchInsert';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=500000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=500000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime) FROMprocess_spend_time_result p WHERE p.plimit=500000 and p.pmethod='batchInsertWithTransaction2';

 

3.6.1.2       秒级SQL【time(s)】

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=10000 and p.pmethod='batchInsertWithTransaction2';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsert2';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=50000 and p.pmethod='batchInsertWithTransaction';

SELECTAVG(p.ptime)/1000 FROM process_spend_time_resultp WHEREp.plimit=50000 andp.pmethod='batchInsertWithTransaction2';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p WHERE p.plimit=100000 and p.pmethod='batchInsert';

SELECTAVG(p.ptime)/1000 FROMprocess_spend_time_result p

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/boonya/article/details/70157820
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-03-01 22:43:09
  • 阅读 ( 1059 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢