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

2023-11-10

http://blog.csdn.net/boonya/article/details/70157820


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

 

 

Author:boonya

 

Date:2017-04-13

 

1      背景

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

 

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

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

     insert into userinfo (uidunameuphoneuaddress)

     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 WHERE p.plimit=100000 and p.pmethod='batchInsert2';

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

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

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

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

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

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

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

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

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

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

 

3.6.2  测试数据汇总

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

测试样例

1W(s)               

5W(s)               

10W(s)              

25W(s)                

50W(s)                               

普通插入

28.70

191.91

367.42

1040.82

2011.82

普通+事务

1.64

12.81

21.91

49.29

122.81

批量插入

32.38

223.00

385.83

1199.02

1980.54

批量+事务

2.37

15.51

18.63

69.71

112.57

3.7  JDBC测试规律总结

3.7.1  规律一:批量插入尽量使用事务控制

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

测试样例

1W(s)               

5W(s)                

10W(s)              

25W(s)               

50W(s)                               

普通插入

28.70

191.91

367.42

1040.82

2011.82

普通+事务

1.64

12.81

21.91

49.29

122.81

批量插入

32.38

223.00

385.83

1199.02

1980.54

批量+事务

2.37

15.51

18.63

69.71

112.57

 

3.7.2  规律二:事务批量处理的数据量不要太大

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

测试样例

1W(s)              

5W(s)                 

10W(s)              

25W(s)                

50W(s)                               

普通插入

28.70

191.91

367.42

1040.82

2011.82

普通+事务

1.64

12.81

21.91

49.29

122.81

批量插入

32.38

223.00

385.83

1199.02

1980.54

批量+事务

2.37

15.51

18.63

69.71

112.57

3.7.3  规律三:适当地设置MySQL参数可以提高数据库性能

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

测试样例

1W(s)              

5W(s)                 

10W(s)              

25W(s)                 

50W(s)                             

普通插入

28.70

191.91

367.42

1040.82

2011.82

普通+事务

1.64

12.81

21.91

49.29

122.81

批量插入

32.38

223.00

385.83

1199.02

1980.54

批量+事务

2.37

15.51

18.63

69.71

112.57

3.7.4  规律四:处理数据量和时间不是成倍增长

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

测试样例

1W(s)              

5W(s)                 

10W(s)              

25W(s)                  

50W(s)                            

普通插入

28.70

191.91

367.42

1040.82

2011.82

普通+事务

1.64

12.81

21.91

49.29

122.81

批量插入

32.38

223.00

385.83

1199.02

1980.54

批量+事务

2.37

15.51

18.63

69.71

112.57

3.7.5  规律五:数据库性能随数据量的不断加大而降低

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

测试样例

1W(s)                

5W(s)               

10W(s)              

25W(s)                  

50W(s)                            

普通插入

28.70

191.91

367.42

1040.82

2011.82

普通+事务

1.64

12.81

21.91

49.29

122.81

批量插入

32.38

223.00

385.83

1199.02

1980.54

批量+事务

2.37

15.51

18.63

69.71

112.57

 

4      结论

经过以上测试得出结论:Mybatis的批量适合处理少了数据的批量处理,而JDBC适合大数据量的批量处理。据此,采用JDBC批量+事务处理大数据量的表插入操作是最合适的。

5      方案

因为要考虑JVM的GC所以数据应该限制一下,但鉴于Mybatis大数据量的批量插入效率不高,所以根据数据大小分段治理。

 

5.1  小于1W使用:Mybatis批量插入方案

对JVM进行调优,但主要的性能瓶颈在批量插入操作。鉴于mybatis在项目开发方面的优势,数据量很小的情况下还是建议使用Mybatis。

 

5.2  大于1W小于10W使用:JDBC批量+事务处理

对JVM进行调优(设置Stack和GC等)。一般操作30秒以内是可以容忍的性能耗时。

5.3  10W以上数据使用:数据分批+JDBC批量+事务处理

对JVM进行调优(设置Stack和GC等),通过数据分批处理。对于分批处理需要借鉴前面的测试数据来定义分批量的大小,主要是对操作时间调优。

 

如果是100W1000W级别的数据量,分批处理可以很大程度地提升插入效率,具体的分批需要通过实践去分配,数据量太大这里就不做实验了。

6      参考资料

JDBC实现往MySQL数据库插入百万数据:http://www.cnblogs.com/fnz0/p/5713102.html

 

 

MySQL Max_allowed_packet: http://stackoverflow.com/questions/8062496/how-to-change-max-allowed-packet-size

 

Spring Mybatis和Spring JDBC的插入效率比较:http://toplchx.iteye.com/blog/1988254

 

注:另外一种比较高效的导入方式是生成一个文本文件使用MySQL的JDBC LOAD DATA LOCAL INFILE;参考示例:

MySQL使用JDBC LOAD DATA LOCAL INFILE导入注意事项

MySQL使用LOAD DATA LOCAL INFILE数据3-5秒导入40W数据

Java不写文件,LOAD DATA LOCAL INFILE大批量导入数据到MySQL的实现

7.实战演练

注意:事务处理的数据量不能太多。

7.1  JDBC工具类

 

package com.wlyd.fmcgwms.util.jdbc;

 

import java.io.IOException;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.SQLException;

import java.util.Properties;

/**

 *JDBC连接工具类

 *

 *@package com.wlyd.fmcgwms.util.jdbc.JdbcConnection

 *@date   2017年4月17日  下午3:32:15

 *@author pengjunlin

 *@comment  

 *@update

 */

public class JdbcConnection {

        

         privatestatic Connection conn = null; 

        

   private static Properties props = null; 

 

   static { 

       props = new Properties(); 

       try { 

           props.load(JdbcConnection.class.getResourceAsStream("/jdbc.properties")); 

       } catch (IOException e1) { 

           e1.printStackTrace(); 

       } 

       try { 

           Class.forName(props.getProperty("jdbc.driverClass")); 

       } catch (ClassNotFoundException e) { 

           e.printStackTrace(); 

       } 

    }

 

   public static Connection getConn(){ 

       try { 

           conn = DriverManager.getConnection(props.getProperty("jdbc.jdbcUrl"),props.getProperty("jdbc.user"),props.getProperty("jdbc.password")); 

           conn.setAutoCommit(false); 

       } catch (SQLException e) { 

           e.printStackTrace(); 

       } 

       return conn; 

   } 

     

   public void closeConn(){ 

       try { 

           if (conn != null) 

                conn.close(); 

       } catch (SQLException e) { 

           e.printStackTrace();

       } 

         

   } 

 

}

 

7.2  批量事务插入

7.2.1  接口

 /**

     jdbc批量插入

     *

     @MethodName: jdbcBatchInsert

     @Description:

     @param user

     @param items

     @return

     @throws Exception

     @throws

     */

    int jdbcBatchInsert(EsUser user,List<WmElectronicSheetItem> itemsthrows Exception;

   

    /**

     * jdbc批量插入

     *

     * @MethodName: jdbcPerBatchInsert

     * @Description:

     * @param user

     * @param items

     * @return

     * @throws Exception

     * @throws

     */

    intjdbcPerBatchInsert(EsUser user, List<WmElectronicSheetItem> items)  throws Exception;

7.2.2  实现

@Override

    publicint jdbcBatchInsert(EsUser userList<WmElectronicSheetItem> itemsthrows Exception {

        intflag = 0;

 

        intperCount = 100, index = 0;

 

        inttimes = items.size() / perCount;

        longstime=System.currentTimeMillis();

        try {

            do {

                // 休眠50ms

                Thread.sleep(50);

                List<WmElectronicSheetItem>listTempnull;

                if (items.size() >= perCount) {

                    listTemp = items.subList(0, perCount);// listTemp是分段处理逻辑的参数

                }else{

                    listTemp = items.subList(0, items.size());// listTemp是分段处理逻辑的参数

 

                }

                // 遍历当前的值是否正确

                Stringresult"";

                for (inti = 0; i < listTemp.size(); i++) {

                    result += listTemp.get(i) + ",";

                }

                Log.getLogger(getClass()).info("" + (index+1)+ ":>>" + result);

               

                // 事务单元执行个数==尽量在事务里面处理少一点(事务尽量小一点)

                jdbcPerBatchInsert(userlistTemp);

 

                items.removeAll(listTemp);

 

                Log.getLogger(getClass()).info("当前剩余集合长度:>>" + items.size());

 

                index++;

            }while(index<= times);

            // 计算时间

            longetime=System.currentTimeMillis();

            Log.getLogger(getClass()).info(">>封装面单号批量事务插入总共耗时-----------------------:"+(etime-stime)+"ms!");

        }catch(Exception e) {

            e.printStackTrace();

            flag=2;

            Log.getLogger(getClass()).error("JDBC批量执行插入异常:>>" + items.size());

            thrownew RuntimeException();

        }

 

        returnflag;

    }

 

 

    @Override

    publicintjdbcPerBatchInsert(EsUser user, List<WmElectronicSheetItem> items)

            throws Exception {

        intflag=0;

        Connectionconn=JdbcConnection.getConn();

        PreparedStatementpstmnull;

        try {

            Stringsql"insert intowm_electronic_sheet_item_?  ("

                    +"WESI_WESB_ID,WESI_CARRIER_CODE,WESI_START_CHARACTER,WESI_SEQUENCE,"

                    +"WESI_WAREHOUSE_ID, WESI_CODE,WESI_STATE, "

                    +"CREATOR, CREATE_TIME, MODIFIER,MODIFY_TIME) values"

                    +"(?, ?, ?,  ?, ?, ?, ?, ?, ?, ?, ?)";

            conn.setAutoCommit(false);

            Log.getLogger(getClass()).info(">>>>>>验证JDBC连接:"+(conn!=null));

            for (inti = 0, j = items.size(); i < ji++) {

                WmElectronicSheetItemitemitems.get(i);

                pstm = conn.prepareStatement(sql);

                pstm.setInt(1, Integer.valueOf(user.getEsCorCode())); // tableName

                pstm.setInt(2, item.getWesiWesbId());// WESI_WESB_ID

                pstm.setString(3, item.getWesiCarrierCode());// WESI_CARRIER_CODE

                pstm.setString(4, item.getWesiStartCharacter());// WESI_START_CHARACTER

                pstm.setString(5, item.getWesiSequence());// WESI_SEQUENCE

                pstm.setInt(6, item.getWesiWarehouseId());// WESI_WAREHOUSE_ID

                pstm.setString(7, item.getWesiCode());// WESI_CODE

                pstm.setInt(8, item.getWesiState());// WESI_STATE

                pstm.setInt(9, user.getEsId());// CREATOR

                pstm.setTimestamp(10,new java.sql.Timestamp(new Date().getTime()));// CREATE_TIME

                pstm.setInt(11, -1);// MODIFIER

                pstm.setTimestamp(12, null);// MODIFY_TIME

                pstm.executeUpdate();

            }

            conn.commit();// 手动提交事务

        }catch(Exception e) {

            e.printStackTrace();

            flag=2;

            Log.getLogger(getClass()).error("JDBC批量分配事务单元执行插入异常:>>" + items.size());

            thrownew RuntimeException();

        }finally{

            if (pstm != null) {

                try {

                    pstm.close();

                }catch(SQLException e) {

                    e.printStackTrace();

                }

            }

            if (conn != null) {

                conn.close();

            }

        }

        returnflag;

    }

7.3测试一组数据

测试50000条数据耗时统计:

数据样本事务大小 (每个事务处理的数量)                                

         耗时(ms)                                             

100

100258

500

75041

1000

68850

3000

78354


通过这种方式提交比较安全不会出现线程锁表问题,事务处理尽量少,根据每次事务提交执行的量可以实现时间上的优化。


本文测试文档代码和数据库均已上传:http://download.csdn.net/detail/boonya/9812860


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

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

  • 使用 Eclipse 将具有外部依赖项的 Java 项目导出到 jar

    有没有一种简单的方法可以将 Java 项目 包括其所有外部依赖项 导出到标准 jar 文件 我开发了一个使用多个 Apache 库的 SDK 我希望能够将该项目作为单个 jar 发布 到目前为止我找到的这个问题的答案要求将项目打包为 Run
  • HttpSession 内的同步是否可行?

    UPDATE 问题后立即解决 问题 通常 同步是在 JVM 内序列化并行请求 例如 private static final Object LOCK new Object public void doSomething synchroniz
  • 如何停止使用扫描仪从标准输入读取多行?

    我正在做一个 JAVA 作业 应该处理多行输入 指令显示 输入是从标准输入读取的 给出了示例输入的示例 one 1 two 2 three 3 我不明白上面的示例输入 从标准输入读取 是什么意思 这是我编写的一个测试程序 它可以消除我的困惑
  • 为什么这个动作不抽象? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 我很难理解为什么一个类中的一个操作是抽象的 而另一个类中的操作不是 源代码1 编译时出错 https gyazo com cd3c
  • 限制 JPQL 中的结果数量

    如何限制从数据库检索结果的数量 select e from Entity e I need only 10 results for instance 您可以尝试像这样给出 10 个要显式获取的结果 entityManager createQ
  • 为什么我的 @OneToMany 属性出现主键违规?

    我有一个实体 Entity public class Student GeneratedValue strategy GenerationType AUTO Id private long id OneToMany private Set
  • Java - toString 到 Color

    我一整天都在努力解决这个问题 基本上我做了一个 for 循环 将条目添加到数组列表中 其中一项是 颜色 变量 我已经用过random nextInt为颜色构造函数的红色 绿色和蓝色部分创建新值 我还设置了一个toString方法 这样我就可
  • Java:不使用 Arrays.sort() 对整数数组进行排序

    这是我们 Java 课程的练习之一中的说明 首先 我想说我 做了我的功课 我不仅仅是懒惰地请 Stack Overflow 上的人帮我回答这个问题 在所有其他练习中 这个特定项目一直是我的问题 因为我一直在努力寻找 完美的算法 编写JAVA
  • 如何构建和使用 TimeSeriesCollections

    我想在图表的 X 轴上显示一些日期 并且here https stackoverflow com questions 5118684 jfreechart histogram with dates据说我必须使用 TimeSeriesColl
  • Hazelcast:连接到远程集群

    我们有一组 Hazelcast 节点 全部运行在一个远程系统 具有许多节点的单个物理系统 上 我们希望从外部客户端连接到该集群 一个 Java 应用程序 它使用如下代码连接到 Hazelcast ClientConfig clientCon
  • 如何将测试类打包到jar中而不运行它们?

    我正在努力将我的测试类包含到 jar 包中 但不运行它们 经过一番谷歌搜索后 我尝试过mvn package DskipTests 但我的测试类根本没有添加到 jar 中 有任何想法吗 如果您遵循 Maven 约定 那么您的测试类位于src
  • Java8 项目上的 SonarQube 给出 jacoco-Exception

    我刚刚下载了最新版本 SonarQube 4 3 然后尝试使用以下命令构建 java 8 项目 mvn clean install mvn sonar sonar 这给了我下面的例外 谷歌搜索 我的印象是这是一个早期的问题 应该已经解决 h
  • 将 PropertyPlaceholderConfigurer 中的所有属性注入到 bean 中

    我有一个PropertyPlaceholderConfigurer加载多个属性文件 我想通过配置 XML 将合并的属性映射注入到 Spring Bean 中 我可以这样做以及如何做 您只需创建一个属性 bean 并将其用于您的Propert
  • 如何在 Java 中创建一个带有连字符的值的静态枚举?

    如何创建如下所示的静态枚举 static enum Test employee id employeeCode 截至目前 我遇到了错误 这对于 Java 来说是不可能的 因为每个项目都必须是有效的标识符 并且有效的 Java 标识符可能不包
  • Javac 版本 1.7 无法为目标 1.7 构建

    我试图在 Linux Mint 系统上使用 Sun Java JDK 1 7 0 17 编译 Java 代码 但遇到了这个问题 javac version target 1 7 javac 1 7 0 17 javac invalid ta
  • 接口中“不能降低继承方法的可见性”的含义

    我有两个文件 public interface PrintService void print PrintDetails details class PrintDetails private String printTemplate pub
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad
  • while循环只执行一次

    我很难弄清楚为什么 while 循环实际上不会循环 它运行一次并停止 import java util public class mileskm public static void main String args Scanner inp
  • 如何让JComboBox中的内容居中显示?

    目前我有这个JComboBox 我怎样才能将其中的内容居中 String strs new String 15158133110 15158133124 15158133458 JComboBox com new JComboBox str
  • Swing:创建可拖动组件...?

    我在网上搜索了可拖动 Swing 组件的示例 但我发现示例不完整或不起作用 我需要的是一个摇摆组件那可以是dragged通过鼠标 在另一个组件内 被拖拽的时候 应该已经 改变它的位置 而不仅仅是 跳 到目的地 我很欣赏无需非标准 API 即

随机推荐

  • 使用springcloud feign时 token认证

    我们在项目中使用feign进行调用时 往往需要进行身份验证 而feignclient需要按照http调用方的格式来书写 这时候呢 我们可以使用这种方式来进行加入身份验证 public class FeignConfig implements
  • tcp服务端通讯+按键发送协议

    import threading import socket import json import keyboard TCP服务器配置 HOST 0 0 0 0 PORT 8888 创建TCP服务端 server socket socket
  • kodi 下载插件失败/无法刮削

    kodi 下载插件失败 无法刮削 很有可能是被墙 或者DNS被污染 解决的方法很简单 修改host 并不是修改nas win kodi上的host 一个一个修改太麻烦了 而是在路由器上修改host 这样一来所有的设备都可以使用了 现在的路由
  • 【C++】STL初识

    目录 STL背景和定义 STL分类 STL三大分类 容器 算法 迭代器 STL六大组件 STL容器使用案例 创建容器 遍历容器 容器嵌套容器 STL背景和定义 STL是标准模板库 Standard Template Library STL
  • 基础算--简单枚举

    简单枚举 顾名思义 枚举便是依次列举出所有可能产生的结果 根据题中的条件对所得的结果进行逐一的判断 过滤掉那些不符合要求的 保留那些符合要求的 也可以称之为暴力算法 枚举结构 循环 判断语句 应用场合 在竞赛中 并不是所有问题都可以使用枚举
  • 【Vue3】SplitPane 可拖拽分隔面板组件

    1 效果图 2 组件完整代码
  • 算法笔记--最大连续1的个数Ⅲ

    leetcode题目链接 1004 最大连续1的个数 III 题目描述 给定一个二进制数组 nums 和一个整数 k 如果可以翻转最多 k 个 0 则返回 数组中连续 1 的最大个数 思路 这里可以转换思路 让题意更加明确 即 求一个最大连
  • 五十六.L1-017 到底有多二

    include
  • 【华为机试题】华为机试真题附解答(2020.9.16/c++)

    第一题题目描述 五键键盘只可以输入a ctrl c ctrl x ctrl v ctrl a 对应的功能为 a 输出到屏幕上a字母 ctrl c 复制选定内容到剪贴板 ctrl x 复制选定内容到剪贴板并且清空当前选定内容 ctrl v 将
  • Vue.js面试题整理

    一 什么是MVVM MVVM是Model View ViewModel的缩写 MVVM是一种设计思想 Model 层代表数据模型 也可以在Model中定义数据修改和操作的业务逻辑 View 代表UI 组件 它负责将数据模型转化成UI 展现出
  • 刷脸支付的产品也在慢慢的完善当中

    如今 春暖花开 万物复苏 在经历了疫情的严冬之后 相信 真正的春天即将来临 在这样的背景下 刷脸支付 这一被疫情耽误了的新的支付方式 或许将迎来一次全新的爆发 说 2019年被称为刷脸支付的元年 在很多人满怀期待刷脸支付或将在2020年进一
  • Java实现加密(一)AES加解密

    目录 1 背景知识 2 AES简介 3 AES的加密过程 AES处理单位 字节 4 Java实现 4 1 生成密钥和偏移量 4 2 AESUtil java 源码 4 3 执行结果 4 4 线上验证 1 背景知识 在密码学中 加密算法分为单
  • facebook 邀请好友

    话不多说 直接上代码了 邀请好友 public void sendFilteredChallenge final Vector
  • 多表连接查询详解

    1 1 多表连接查询的概念 由于数据库中很多数据被分散到多个数据库表中 在查询数据时就经常出现要查的数据来自多个表中 此时就必须采用多表连接查询 多表连接查询是数据库查询中常见的查询方式 多表连接查询分为内连接和外连接 1 2 内连接的概念
  • vpd安全策略的使用

    1 首先我们创建用户vpd 并给与一定的权限 create user vpd identified by 123456 grant resource connect to vpd grant execute on dbms rls to v
  • 电脑无法登录microsoft账号怎么办?

    电脑登录Microsoft账号的方法 请按以下步骤进行 打开控制面板 右键点击左下角的Windows徽标就可以看见弹出菜单有这个选项 win10系统则可以通过搜索功能直接查到控制面板 进入控制面板后把查看方式改为大图标 然后选择网络和共享中
  • 硬核!八张图搞懂 Flink 端到端精准一次处理语义 Exactly-once(深入原理,建议收藏)

    Flink 在 Flink 中需要端到端精准一次处理的位置有三个 Source 端 数据从上一阶段进入到 Flink 时 需要保证消息精准一次消费 Flink 内部端 这个我们已经了解 利用 Checkpoint 机制 把状态存盘 发生故障
  • PAT-哈夫曼树(list、collection)

    Huffuman树 qdulq 40 分 Huffman树在编码中有着广泛的应用 在这里 我们只关心Huffman树的构造过程 给出一列数 pi p0 p1 pn 1 用这列数构造Huffman树的过程如下 1 找到 pi 中最小的两个数
  • 加密套件ECDHE_SM2_WITH_SM4_SM3及握手分析

    应证监局要求 国内金融产品程序化交易软件应采用国密算法实现SSL TLS通讯 我司采用开源项目GmSSL2 0实现 加密套件选用ECDHE SM2 WITH SM4 SM3 其中协议版本为TLS1 2 密钥交换 Key Exchange 算
  • Mybatis与JDBC批量插入MySQL数据库性能测试及解决方案

    http blog csdn net boonya article details 70157820 Mybatis与JDBC批量插入MySQL数据库性能测试 Author boonya Date 2017 04 13 1 背景 系统中需要