JDBC批量Insert深度优化

合集下载

JDBC批量插入数据优化,使用addBatch和executeBatch

JDBC批量插入数据优化,使用addBatch和executeBatch

JDBC批量插⼊数据优化,使⽤addBatch和executeBatchJDBC批量插⼊数据优化,使⽤addBatch和executeBatchSQL的批量插⼊的问题,如果来个for循环,执⾏上万次,肯定会很慢,那么,如何去优化呢?解决⽅案:⽤ preparedStatement.addBatch()配合preparedStatement.executeBatch()去批量插⼊;效率要⽐⼀条⼀条插⼊快近60倍。

代码://获取要设置的Arp基准的List后,插⼊Arp基准表中public boolean insertArpStandardList(List<ArpTable> list) {Connection conn = null;PreparedStatement ps = null;ResultSet rs = null;//MySql的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现⾼性能的批量插⼊。

//优化插⼊性能,⽤JDBC的addBatch⽅法,但是注意在连接字符串加上⾯写的参数。

//例如: String connectionUrl="jdbc:mysql://192.168.1.100:3306/test?rewriteBatchedStatements=true" ;String sql = "insert into arp_standard(guid, devicebrand, devicename, deviceip, ipaddress, " +"macaddress, createtime) values(?,?,?,?,?,?,?)";try{conn = DBConnection.getConnection();ps = conn.prepareStatement(sql);//优化插⼊第⼀步设置⼿动提交conn.setAutoCommit(false);int len = list.size();for(int i=0; i<len; i++) {ps.setString(1, list.get(i).getGuid());ps.setString(2, list.get(i).getDeviceBrand());ps.setString(3, list.get(i).getDeviceName());ps.setString(4, list.get(i).getDeviceIp());ps.setString(5, list.get(i).getIpAddress());ps.setString(6, list.get(i).getMacAddress());ps.setString(7, list.get(i).getCreateTime());//if(ps.executeUpdate() != 1) r = false; 优化后,不⽤传统的插⼊⽅法了。

数据库的批量插入与批量删除优化(五)

数据库的批量插入与批量删除优化(五)

数据库的批量插入与批量删除优化引言数据库操作是现代应用程序中不可或缺的一部分。

在大型应用中,处理大量数据时,批量插入和批量删除操作的效率会直接影响整个系统的性能。

本文将探讨如何优化数据库的批量插入和批量删除操作,提高系统的性能。

一、批量插入的优化批量插入操作是指一次性将多个数据记录插入数据库中。

一般来说,使用批量插入可以减少与数据库的交互次数,提高插入效率。

下面将介绍一些优化方法。

1. 使用批量插入语句传统的插入操作是使用INSERT语句逐条插入数据。

而批量插入则是使用INSERT语句一次性插入多条数据。

这样可以减少与数据库的通信次数,提高插入效率。

在MySQL中,可以使用INSERT INTO ... VALUES (value1), (value2), ...的语法实现批量插入。

2. 设置合适的批量大小在进行批量插入时,需要考虑每次插入的数据量。

如果批量大小设置得太大,可能会导致内存占用过高;如果批量大小设置得太小,插入效率可能会受到影响。

需要根据系统的实际情况进行调整,找到一个合适的批量大小。

3. 关闭自动提交在进行批量插入操作时,可以考虑关闭数据库的自动提交功能。

每次插入数据时,数据库都会进行一次提交操作,这会消耗一定的时间。

关闭自动提交后,可以在插入完所有数据之后,再进行一次提交操作,从而提高插入效率。

二、批量删除的优化批量删除操作是指一次性删除多个数据记录。

与批量插入类似,批量删除也需要考虑一些优化方法,以提高删除效率。

1. 使用批量删除语句与插入操作类似,传统的删除操作是使用DELETE语句逐条删除数据。

而批量删除则是使用DELETE语句一次性删除多条数据。

同样地,批量删除也可以减少与数据库的通信次数,提升删除效率。

2. 设置合适的批量大小在进行批量删除时,也需要考虑每次删除的数据量。

根据实际情况进行调整,找到一个合适的批量大小。

过大的批量删除可能会导致锁表时间过长,影响其他操作的执行。

jdbctemplate插入大量数据提高效率的方法

jdbctemplate插入大量数据提高效率的方法

jdbctemplate插入大量数据提高效率的方法使用批处理操作是提高JdbcTemplate插入大量数据效率的方法之一。

可以通过以下步骤实现:1. 创建一个包含所有要插入的数据的列表。

2. 使用JdbcTemplate的`batchUpdate()`方法执行批处理操作。

- 将INSERT语句作为参数传递给`batchUpdate()`方法。

- 将数据列表作为批处理的输入参数。

3. 在INSERT语句中使用占位符来代替具体的值。

- 使用`?`作为占位符。

- 在INSERT语句的VALUES子句中提供相应的占位符。

4. 使用`batchUpdate()`方法执行批处理操作。

以下是一个示例代码:```javapublic void insertBatchData(List<Data> dataList) {String sql = "INSERT INTO table_name (column1, column2, ...) VALUES (?, ?, ...)";jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() {@Overridepublic void setValues(PreparedStatement ps, int i) throws SQLException {Data data = dataList.get(i);ps.setString(1, data.getValue1());ps.setInt(2, data.getValue2());// 设置其他占位符对应的值}@Overridepublic int getBatchSize() {return dataList.size();}});}```注意事项:- 在使用`batchUpdate()`方法执行批处理操作时,通常需要将数据分成较小的批次进行插入。

jdbc批量插入操作参数

jdbc批量插入操作参数

jdbc批量插入操作参数JDBC是JavaDatabaseConnectivity的缩写,是Java语言访问关系型数据库的一种标准接口。

JDBC提供了一系列的API,可以让Java程序与关系型数据库进行交互。

在JDBC中,批量插入操作可以大大提高数据的插入效率,特别是在需要插入大量数据时。

下面介绍一些JDBC批量插入操作中的参数。

1. addBatch()方法在批量插入操作中,需要使用addBatch()方法将SQL语句添加到批处理中。

该方法的参数是SQL语句。

例如:String sql = 'insert into user(name, age) values('张三', 20)';statement.addBatch(sql);2. executeBatch()方法在将SQL语句添加到批处理中后,需要执行executeBatch()方法来执行批处理。

该方法返回一个int数组,数组中的每个元素表示执行每个SQL语句所影响的行数。

例如:int[] result = statement.executeBatch();3. setXxx()方法在插入数据时,需要使用setXxx()方法为SQL语句中的占位符(?)赋值。

参数Xxx表示占位符的数据类型。

例如:String sql = 'insert into user(name, age) values(?, ?)'; PreparedStatement statement =connection.prepareStatement(sql);statement.setString(1, '张三');statement.setInt(2, 20);4. setBatchSize()方法setBatchSize()方法用于设置批量处理时一次提交的数据量。

默认情况下,批量处理的数据量为1。

例如:connection.setAutoCommit(false);statement.setBatchSize(1000);以上就是JDBC批量插入操作中的一些参数介绍。

数据库的批量插入与批量删除优化(一)

数据库的批量插入与批量删除优化(一)

数据库的批量插入与批量删除优化在现代大数据时代,数据库作为数据存储的核心工具,扮演着至关重要的角色。

然而,随着数据量的不断增长,数据库的性能问题也逐渐凸显出来。

在实际开发中,数据库的批量插入与批量删除操作是非常常见的,因此优化这两个操作将对整体性能产生重要影响。

本文将就数据库的批量插入与批量删除进行优化的相关技术进行论述。

一、批量插入优化1. 使用预编译语句数据库的批量插入可以通过使用预编译语句来提高插入效率。

预编译语句是在执行之前对SQL语句进行编译,并将其缓存起来,减少了每次执行SQL语句时都需要进行编译的时间。

这样,当我们需要批量插入大量数据时,只需执行一次预编译的SQL语句,然后将参数逐个绑定即可。

这种方式可以大大减少数据库的访问时间。

2. 批量提交事务在进行批量插入操作时,可以将多个插入操作放在一个事务中,然后统一进行提交。

这样可以减少与数据库的IO交互次数,提高插入效率。

如果每次插入都是一个事务,那么每次都会有事务开启、提交或回滚的开销,而批量提交事务可以大幅度减少这些开销。

3. 使用批量插入语句数据库提供了一些批量插入语句,如MySQL的INSERT INTO ... VALUES (值1), (值2), ...,这些语句可以一次性插入多行数据,减少了命令的传输时间和与数据库的通信次数,大幅度提高了插入效率。

这种方式适用于需要大量重复的插入数据,比如初始化数据,不适合每次都是不同的数据。

二、批量删除优化1. 适当选择删除策略数据库的批量删除操作可以根据具体需求选择不同的删除策略。

比如当需要删除大量数据时,可以选择直接删除整个表,而不是逐行删除。

这样可以减少IO操作,提高删除效率。

另外,可以考虑使用TRUNCATE语句来清空整个表,而不是使用DELETE语句逐行删除,因为TRUNCATE语句执行效率更高。

2. 合理设置索引索引是数据库查询和删除操作的重要组成部分。

在进行批量删除操作时,如果表中存在索引,那么删除操作会涉及索引的维护,导致删除效率变低。

mybatis批量插入批量修改的写法

mybatis批量插入批量修改的写法

mybatis批量插⼊批量修改的写法1、jdbc链接修改jdbc.driver=com.mysql.jdbc.Driverjdbc.url=jdbc:mysql://localhost:3306/ssm?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&rewriteBatchedStatements=true ername=rootjdbc.password=root2、批量插⼊<insert id="INSERT_BATCH_HOTEL_REAL_PRICE" parameterType="java.util.List">INSERT IGNORE INTO VST_HOTEL_REAL_TIME_PRICE (PRODUCT_ID,REAL_TIME_PRICE1,REAL_TIME_PRICE2,REAL_TIME_REMAIN1,REAL_TIME_REMAIN2,UPDATE_TIME) VALUES<foreach collection="list" item="item" index="index" separator=",">(#{item.productId},#{item.realTimePrice1},#{item.realTimePrice2},#{item.realTimeRemain1},#{item.realTimeRemain2},NOW())</foreach></insert>3、批量修改<update id="UPDATE_HOTEL_REAL_TIME_PRICE" parameterType="java.util.List"><foreach collection="list" item="item" index="index" separator=";">UPDATE VST_HOTEL_REAL_TIME_PRICE<set><if test="item.realTimePrice1 != null">REAL_TIME_PRICE1 = #{item.realTimePrice1},</if><if test="item.realTimePrice2 != null">REAL_TIME_PRICE2 = #{item.realTimePrice2},</if><if test="item.realTimeRemain1 != null">REAL_TIME_REMAIN1 = #{item.realTimeRemain1},</if><if test="item.realTimeRemain2 != null">REAL_TIME_REMAIN2 = #{item.realTimeRemain2},</if>UPDATE_TIME = NOW()</set>WHERE PRODUCT_ID = ${item.productId}</foreach></update>。

数据库的批量插入与批量删除优化(八)

数据库的批量插入与批量删除优化现在的信息时代,数据量呈指数级增长,数据库的存储和管理已经成为一项重要的工作。

其中,批量插入和批量删除操作是数据库中常用的操作之一。

在数据量较大的情况下,如何优化批量插入和批量删除过程,提高数据库的性能,成为了数据库管理员和开发者关注的焦点。

一、批量插入优化批量插入是指一次性插入多条数据到数据库中,相比于逐条插入,批量插入能够大幅度提高数据库的性能。

以下是一些常见的批量插入优化方法:1. 使用事务:将多个插入操作放在一个事务中,可以降低数据库的锁竞争,提高插入效率。

事务的使用可以将多个独立的插入操作合并成一个整体,避免了频繁的连接和断开数据库的开销。

2. 使用批量插入语句:不同的数据库提供了不同的批量插入语句,如MySQL的INSERT INTO ... VALUES (),(),()...,使用这种方式可以一次插入多条数据。

这样可以减少客户端和数据库之间的网络通信次数。

3. 使用索引:在批量插入之前,先建立好必要的索引。

索引能够提高查询的效率,但是在插入过程中会带来一定的开销。

因此,在批量插入之后,再创建索引可以加快插入速度。

4. 关闭或减少触发器和约束:在批量插入的过程中,关闭触发器和约束可以减少对数据库性能的影响。

可以在批量插入前将触发器和约束暂时禁用,插入完成后再重新启用。

二、批量删除优化批量删除是指一次性删除多条数据,同样可以通过一些优化方法提高数据库的性能。

以下是一些常见的批量删除优化方法:1. 使用事务:与批量插入类似,使用事务将多个删除操作合并在一个事务中,减少锁竞争,提高删除效率。

2. 批量删除语句:不同的数据库提供了不同的批量删除语句,如MySQL的DELETE FROM ... WHERE ...。

与批量插入类似,使用批量删除语句可以一次删除多条数据,减少网络通信次数。

3. 使用索引:在批量删除之前,先建立好必要的索引。

索引可以加快删除操作的速度,提高数据库的性能。

oracle的数据批量插入-优化

oracle的数据批量插⼊-优化向数据库插⼊百万级别的数据时,单个插⼊的效率极低优化⽅式:1:在插⼊前,先备份数据库的索引语句,因为带索引的插⼊效率极低,没有索引时较快2:插⼊时批量插⼊,不能单个插⼊,也不能全部插⼊sql语句insert into tableName(column1, column2, column3...) values(value1,value2,value3...);insert into tableName(column1, column2, column3...) values(value1,value2,value3...);insert into tableName(column1, column2, column3...) values(value1,value2,value3...);在mybatis中的写法:<insert id="insertDataSingleDY">INSERT ALL<foreach collection="dataTestDTOList" item="item" index="index">INTO mms_ocm_jn.MMS_DATA_DYPDYVALUES(sys_guid(),#{item.seq,jdbcType=INTEGER},#{item.stationName,jdbcType=VARCHAR},#{item.dbm,jdbcType=VARCHAR},#{item.simpleTime,jdbcType=VARCHAR},#{item.simpleValue,jdbcType=CLOB})</foreach>SELECT 1 FROM DUAL//解释:insert all into并不表⽰⼀个表中插⼊多条记录,⽽是表⽰多表插⼊各⼀条记录,⽽这多表可以是同⼀个表,就成了单表插⼊多条记录。

MySQL:JDBC批量插入数据的效率

MySQL:JDBC批量插⼊数据的效率平时使⽤mysql插⼊、查询数据都没有注意过效率,今天在for循环中使⽤JDBC插⼊1000条数据居然等待了⼀会⼉就来探索⼀下JDBC的批量插⼊语句对效率的提⾼⾸先进⾏建表create table `user1`(`id` int primary key auto_increment,`phoneNumber` int not null ,`indentity` int not null ,`address` varchar(100),index (id,phoneNumber,indentity))engine =innoDB default charset = utf8mb4;这⾥使⽤了⼀个组合索引,会降低插⼊数据的效率,应该就是我插⼊1000条数据都会感觉慢的主要原因存储引擎是innoDB,据说MyISAM插⼊数据会更快JDBC操作数据库使⽤的是MySql8.0 Class.forName("com.mysql.cj.jdbc.Driver");//不需要建⽴ SSL 连接,需要显⽰关闭。

//allowPublicKeyRetrieval=true 允许客户端从服务器获取公钥。

//时区为UTCString dburl = "jdbc:mysql://localhost:3306/myTest?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";String username = "root";String password = "123456";Connection connection = DriverManager.getConnection(dburl,username,password);PreparedStatement的批量插⼊ String sql = "insert into `user1`(`phoneNumber`, `indentity`, `address`) values (?,?,?)";PreparedStatement preparedStatement = connection.prepareStatement(sql);Date date = new Date();System.out.println(date.toString());for (int i = 1000; i < 2000; i++) {preparedStatement.setInt(1,i+2);preparedStatement.setInt(2,i+101);preparedStatement.setString(3,"dizhi");preparedStatement.addBatch();}preparedStatement.executeBatch();运⾏结果显⽰出,插⼊1000条数据只⽤了16秒for循环暴⼒插⼊数据Date date = new Date();System.out.println(date.toString());for (int i = 4000; i < 5000; i++) {preparedStatement.setInt(1,i+2);preparedStatement.setInt(2,i+101);preparedStatement.setString(3,"dizhi");preparedStatement.execute();}Date date1 = new Date();System.out.println(date1.toString());运⾏结果显⽰⽤了17秒,⽤for循环插⼊和批量插⼊⽤的时间差距并不⼤的,这明显有问题,所以进⾏第⼆次批量插⼊查询然后进⾏第⼆次批量插⼊实验(其实是先第⼆次批量插⼊再⽤的暴⼒for) Date date = new Date();System.out.println(date.toString());//for (int i = 3000; i < 4000; i++) {preparedStatement.setInt(1,i+2);preparedStatement.setInt(2,i+101);preparedStatement.setString(3,"dizhi");preparedStatement.addBatch();}Date date1 = new Date();System.out.println(date1.toString());结果很神奇,第⼆次批量插⼊⽴即完成,完全没有延迟具体原因还需要多多百度,我猜测是MySQL缓存的作⽤,省去了很多交互过程,减少了⽹络传输第三次批量插⼊数据现在距离第⼆次已经过去了很长时间,这次测试是想看看MySQL缓存还在不在Date date = new Date();System.out.println(date.toString());for (int i = 5000; i < 6000; i++) {preparedStatement.setInt(1,i+2);preparedStatement.setInt(2,i+101);preparedStatement.setString(3,"dizhi");preparedStatement.addBatch();}preparedStatement.executeBatch();Date date1 = new Date();System.out.println(date1.toString());显然,⼜是16秒,看来是时间过去太久了总的来说,MySQL是真个神奇的玩意。

JDBC批量插入数据效率分析

JDBC批量插⼊数据效率分析对于需要批量插⼊数据库操作JDBC有多重⽅式,本利从三个⾓度对Statement和PreparedStatement两种执⾏⽅式进⾏分析,总结较优的⽅案。

当前实现由如下条件: 执⾏数据库:Mysql执⾏数据数量:10万条执⾏前提:执⾏差⼊数据库钱均需要提供空表,防⽌数据量⼤造成的影响执⾏⽅式:Statement和PreparedStatement两种⽅式执⾏步骤开始:1、创建表1 CREATE TABLE T_PRODUCT (2 ID bigint(12) NOT NULL AUTO_INCREMENT COMMENT '主键',3 NAME varchar(60) NOT NULL COMMENT '产品名称',4 WEIGHT varchar(60) NOT NULL COMMENT '产品重量',5 MARK varchar(60) NOT NULL COMMENT '产品说明',6 PRIMARY KEY (ID)7 ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='产品表';2、编写操作数据库⼯具类1package com.luwei.test.jdbc;23import java.sql.Connection;4import java.sql.DriverManager;5import java.sql.SQLException;6import java.sql.Statement;7import java.util.ResourceBundle;89/**10 * <Description> TODO<br>11 *12 * @author lu.wei<br>13 * @email 1025742048@ <br>14 * @date 2017年1⽉9⽇ <br>15 * @since V1.0<br>16 * @see com.luwei.test.jdbc <br>17*/18public class JdbcTemplate {19private static String DRIVER_CLASS_NAME = null;20private static String URL = null;21private static String USERNAME = null;22private static String PASSWORD = null;2324static {25 ResourceBundle bundle = ResourceBundle.getBundle("jdbc");26 DRIVER_CLASS_NAME = bundle.getString("jdbc.driverClassName");27 URL = bundle.getString("jdbc.url");28 USERNAME = bundle.getString("ername");29 PASSWORD = bundle.getString("jdbc.password");30 }3132/**33 *34 * <Description> 获取数据库连接<br>35 *36 * @author lu.wei<br>37 * @email 1025742048@ <br>38 * @date 2017年1⽉9⽇下午10:19:41 <br>39 * @return40 * @throws Exception41 * <br>42*/43public static Connection getConnection() throws Exception {44 Class.forName(DRIVER_CLASS_NAME);45 Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);46return connection;47 }4849/**51 * <Description> 提交事务<br>52 *53 * @author lu.wei<br>54 * @email 1025742048@ <br>55 * @date 2017年1⽉9⽇下午10:20:48 <br>56 * @param connection57 * <br>58*/59public static void commit(Connection connection) {60try {61 mit();62 }63catch (SQLException e) {64 e.printStackTrace();65 }66 }6768/**69 *70 * <Description> 开启事务<br>71 *72 * @author lu.wei<br>73 * @email 1025742048@ <br>74 * @date 2017年1⽉9⽇下午10:23:56 <br>75 * @param connection76 * <br>77*/78public static void beginTx(Connection connection) {79try {80 connection.setAutoCommit(false);81 }82catch (SQLException e) {83 e.printStackTrace();84 }85 }8687/**88 *89 * <Description> 回滚<br>90 *91 * @author lu.wei<br>92 * @email 1025742048@ <br>93 * @date 2017年1⽉9⽇下午10:24:33 <br>94 * @param connection95 * <br>96*/97public static void rollback(Connection connection) {98try {99 connection.rollback();100 }101catch (SQLException e) {102 e.printStackTrace();103 }104 }105106/**107 *108 * <Description> TODO<br>109 *110 * @author lu.wei<br>111 * @email 1025742048@ <br>112 * @date 2017年1⽉9⽇下午10:28:49 <br>113 * @param statement114 * @param connection115 * <br>116*/117public static void releaseDb(Statement statement, Connection connection) {118try {119 statement.close();120 connection.close();121 }122catch (SQLException e) {123 e.printStackTrace();124 }125 }126 }3、执⾏数据库插⼊操作3.1、使⽤Statement直接插⼊,三次执⾏耗时:41979 42608 424902public void testStatement() {3 Connection connection = null;4 Statement statement = null;5try {6 connection = JdbcTemplate.getConnection();7 JdbcTemplate.beginTx(connection);89 statement = connection.createStatement();10long begin = System.currentTimeMillis();11for (int i = 0; i < 100000; i++) {12 String sql = "insert into t_product values(null,'name_" + i + "','120kg','mark_" + i + "')";13 statement.execute(sql);14 }15long end = System.currentTimeMillis();16 System.out.println(end - begin);17 mit(connection);18 }19catch (Exception e) {20 e.printStackTrace();21 JdbcTemplate.rollback(connection);22 }23finally {24 JdbcTemplate.releaseDb(statement, connection);25 }26 }3.2、使⽤PreparedStatement直接插⼊,三次执⾏耗时:22808 24675 22281 1 @Test2public void testPreparedStatement() {3 Connection connection = null;4 PreparedStatement statement = null;5try {6 connection = JdbcTemplate.getConnection();7 JdbcTemplate.beginTx(connection);8 String sql = "insert into t_product values(null,?,?,?)";910 statement = connection.prepareStatement(sql);11long begin = System.currentTimeMillis();12for (int i = 0; i < 100000; i++) {13 statement.setString(1, "name_" + i);14 statement.setString(2, "120kg");15 statement.setString(3, "mark_" + i);16 statement.executeUpdate();17 }18long end = System.currentTimeMillis();19 System.out.println(end - begin);20 mit(connection);21 }22catch (Exception e) {23 e.printStackTrace();24 JdbcTemplate.rollback(connection);25 }26finally {27 JdbcTemplate.releaseDb(statement, connection);28 }29 }3.3、使⽤BatchStatement直接插⼊,三次执⾏耗时:15342 15235 154851 @Test2public void testBatchStatement() {3 Connection connection = null;4 Statement statement = null;5try {6 connection = JdbcTemplate.getConnection();7 JdbcTemplate.beginTx(connection);89 statement = connection.createStatement();10long begin = System.currentTimeMillis();11for (int i = 0; i < 100000; i++) {12 String sql = "insert into t_product values(null,'name_" + i + "','120kg','mark_" + i + "')";13 statement.addBatch(sql);1415if ((i + 1) % 100 == 0) {16 statement.executeBatch();17 statement.clearBatch();18 }19 }20 statement.executeBatch();21 statement.clearBatch();22long end = System.currentTimeMillis();23 System.out.println(end - begin);24 mit(connection);25 }26catch (Exception e) {27 e.printStackTrace();28 JdbcTemplate.rollback(connection);29 }30finally {31 JdbcTemplate.releaseDb(statement, connection);32 }33 }3.4、使⽤BatchPreparedStatement直接插⼊,三次执⾏耗时:21913 22045 23291 1 @Test2public void testBatchPreparedStatement() {3 Connection connection = null;4 PreparedStatement statement = null;5try {6 connection = JdbcTemplate.getConnection();7 JdbcTemplate.beginTx(connection);8 String sql = "insert into t_product values(null,?,?,?)";910 statement = connection.prepareStatement(sql);11long begin = System.currentTimeMillis();12for (int i = 0; i < 100000; i++) {13 statement.setString(1, "name_" + i);14 statement.setString(2, "120kg");15 statement.setString(3, "mark_" + i);16 statement.addBatch();17if ((i + 1) % 100 == 0) {18 statement.executeBatch();19 statement.clearBatch();20 }21 }22 statement.executeBatch();23 statement.clearBatch();24long end = System.currentTimeMillis();25 System.out.println(end - begin);26 mit(connection);27 }28catch (Exception e) {29 e.printStackTrace();30 JdbcTemplate.rollback(connection);31 }32finally {33 JdbcTemplate.releaseDb(statement, connection);34 }35 }3.5、使⽤采⽤多Value值Statement直接插⼊,三次执⾏耗时:2931 3007 3203 2964 1 @Test2public void testMutilValueStatement() {3 Connection connection = null;4 Statement statement = null;5try {6 connection = JdbcTemplate.getConnection();7 JdbcTemplate.beginTx(connection);89 statement = connection.createStatement();1011 StringBuffer sql = new StringBuffer("insert into t_product values");12long begin = System.currentTimeMillis();13for (int i = 0; i < 100000; i++) {14if (i != 0) {15 sql.append(",");16 }17 sql.append("(null,'name_" + i + "','120kg','mark_" + i + "')");18 }19 statement.execute(sql.toString());20long end = System.currentTimeMillis();21 System.out.println(end - begin);22 mit(connection);23 }24catch (Exception e) {25 e.printStackTrace();26 JdbcTemplate.rollback(connection);27 }28finally {29 JdbcTemplate.releaseDb(statement, connection);30 }31 }3.6、使⽤采⽤多Value值PreparedStatement直接插⼊,三次执⾏耗时:3356 3218 32331 @Test2public void testMutilValuePreparedStatement() {3 Connection connection = null;4 PreparedStatement statement = null;5try {6 connection = JdbcTemplate.getConnection();7 JdbcTemplate.beginTx(connection);89 StringBuffer sql = new StringBuffer("insert into t_product values");10long begin = System.currentTimeMillis();11for (int i = 0; i < 100000; i++) {12if (i != 0) {13 sql.append(",");14 }15 sql.append("(null,'name_" + i + "','120kg','mark_" + i + "')");16 }17 statement = connection.prepareStatement(sql.toString());18 statement.executeUpdate();19long end = System.currentTimeMillis();20 System.out.println(end - begin);21 mit(connection);22 }23catch (Exception e) {24 e.printStackTrace();25 JdbcTemplate.rollback(connection);26 }27finally {28 JdbcTemplate.releaseDb(statement, connection);29 }30 }通过以上时间结果得出如下数据表格:总结:通过如上的数据对⽐发现 1、PreparedStatement执⾏数据库插⼊⽐使⽤Statement执⾏数据库插⼊明显有性能优势,原因归功于PreparedStatement能够预先对SQL进⾏编译,做到执⾏时进⾏SQL共享 2、执⾏数据库批量操作是使⽤Batch⽅式对数据库采⽤批次操作能够明显提升数据库操作性能能 3、不管是直接多次插⼊数据库还是采⽤Batch⽅式执⾏数据库的插⼊,均会发送多次SQL脚本去执⾏,这样明显没有发送⼀次SQL脚本执⾏来的效率⾼ 4、采⽤单SQL执⾏数据库批量操作时Statement对⽐PreparedStatement有微弱的优势,可能是Statement不需要判断注参的原因吧。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

有时间给我讲讲这个,如果你懂的话。

JDBC批量Insert深度优化(没事务)最近在做一个数据同步分发工具,高并发,高效率,异步非实时是主要特点。

为此,选择的方案是JDBC、只有两种操作,插入和更新。

对于更新,只能逐条分批就可以了,优化空间不大。

对于插入,则可以做批量的优化,优化的策略只能是具体问题具体分析,以测试结论为主要依据了。

环境:MySQL 5.1RedHat Linux AS 5JavaSE 1.5DbConnectionBroker 微型数据库连接池测试的方案:执行10万次Insert语句,使用不同方式。

A组:静态SQL,自动提交,没事务控制(MyISAM引擎)1、逐条执行10万次2、分批执行将10万分成m批,每批n条,分多种分批方案来执行。

B组:预编译模式SQL,自动提交,没事务控制(MyISAM引擎)1、逐条执行10万次2、分批执行将10万分成m批,每批n条,分多种分批方案来执行。

-------------------------------------------------------------------------------------------C组:静态SQL,不自动提交,有事务控制(InnoDB引擎)1、逐条执行10万次2、分批执行将10万分成m批,每批n条,分多种分批方案来执行。

D组:预编译模式SQL,不自动提交,有事务控制(InnoDB引擎)1、逐条执行10万次2、分批执行将10万分成m批,每批n条,分多种分批方案来执行。

本次主要测试A、B组,并得出测试结果。

SQL代码DROP TABLE IF EXISTS tuser;CREATE TABLE tuser (id bigint(20) NOT NULL AUTO_INCREMENT,name varchar(12) DEFAULT NULL,remark varchar(24) DEFAULT NULL,createtime datetime DEFAULT NULL,updatetime datetime DEFAULT NULL,PRIMARY KEY (id)) ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;下面是A、B组的测试代码:package testbatch;import java.io.IOException;import java.sql.*;/*** JDBC批量Insert优化(上)** @author leizhimin 2009-7-29 10:03:10*/public class TestBatch {public static DbConnectionBroker myBroker = null;static {try {myBroker = new DbConnectionBroker("com.mysql.jdbc.Driver","jdbc:mysql://192.168.104.163:3306/testdb","vcom", "vcom", 2, 4,"c:\\testdb.log", 0.01);} catch (IOException e) {e.printStackTrace();}}/*** 初始化测试环境** @throws SQLException 异常时抛出*/public static void init() throws SQLException {Connection conn = myBroker.getConnection();Statement stmt = conn.createStatement();stmt.addBatch("DROP TABLE IF EXISTS tuser");stmt.addBatch("CREATE TABLE tuser (\n" +" id bigint(20) NOT NULL AUTO_INCREMENT,\n" +" name varchar(12) DEFAULT NULL,\n" +" remark varchar(24) DEFAULT NULL,\n" +" createtime datetime DEFAULT NULL,\n" +" updatetime datetime DEFAULT NULL,\n" +" PRIMARY KEY (id)\n" +") ENGINE=MyISAM AUTO_INCREMENT=1 DEFAULT CHARSET=utf8");stmt.executeBatch();myBroker.freeConnection(conn);}/*** 100000条静态SQL插入** @throws Exception 异常时抛出*/public static void testInsert() throws Exception {init(); //初始化环境Long start = System.currentTimeMillis();for (int i = 0; i < 100000; i++) {String sql = "\n" +"insert into testdb.tuser \n" +"\t(name, \n" +"\tremark, \n" +"\tcreatetime, \n" +"\tupdatetime\n" +"\t)\n" +"\tvalues\n" +"\t('" + RandomToolkit.generateString(12) + "', \n" +"\t'" + RandomToolkit.generateString(24) + "', \n" +"\tnow(), \n" +"\tnow()\n" +")";Connection conn = myBroker.getConnection();Statement stmt = conn.createStatement();stmt.execute(sql);myBroker.freeConnection(conn);}Long end = System.currentTimeMillis();System.out.println("单条执行100000条Insert操作,共耗时:" + (end - start) / 1000f + "秒!");}* 批处理执行静态SQL测试** @param m 批次* @param n 每批数量* @throws Exception 异常时抛出*/public static void testInsertBatch(int m, int n) throws Exception {init(); //初始化环境Long start = System.currentTimeMillis();for (int i = 0; i < m; i++) {//从池中获取连接Connection conn = myBroker.getConnection();Statement stmt = conn.createStatement();for (int k = 0; k < n; k++) {String sql = "\n" +"insert into testdb.tuser \n" +"\t(name, \n" +"\tremark, \n" +"\tcreatetime, \n" +"\tupdatetime\n" +"\t)\n" +"\tvalues\n" +"\t('" + RandomToolkit.generateString(12) + "', \n" +"\t'" + RandomToolkit.generateString(24) + "', \n" +"\tnow(), \n" +"\tnow()\n" +")";//加入批处理stmt.addBatch(sql);}stmt.executeBatch(); //执行批处理// stmt.clearBatch(); //清理批处理stmt.close();myBroker.freeConnection(conn); //连接归池}Long end = System.currentTimeMillis();System.out.println("批量执行" + m + "*" + n + "=" + m * n + "条Insert操作,共耗时:" + (end - start) /1000f + "秒!");}* 100000条预定义SQL插入** @throws Exception 异常时抛出*/public static void testInsert2() throws Exception { //单条执行100000条Insert操作,共耗时:40.422秒!init(); //初始化环境Long start = System.currentTimeMillis();String sql = "" +"insert into testdb.tuser\n" +" (name, remark, createtime, updatetime)\n" +"values\n" +" (?, ?, ?, ?)";for (int i = 0; i < 100000; i++) {Connection conn = myBroker.getConnection();PreparedStatement pstmt = conn.prepareStatement(sql);pstmt.setString(1, RandomToolkit.generateString(12));pstmt.setString(2, RandomToolkit.generateString(24));pstmt.setDate(3, new Date(System.currentTimeMillis()));pstmt.setDate(4, new Date(System.currentTimeMillis()));pstmt.executeUpdate();pstmt.close();myBroker.freeConnection(conn);}Long end = System.currentTimeMillis();System.out.println("单条执行100000条Insert操作,共耗时:" + (end - start) / 1000f + "秒!");}/*** 批处理执行预处理SQL测试** @param m 批次* @param n 每批数量* @throws Exception 异常时抛出*/public static void testInsertBatch2(int m, int n) throws Exception {init(); //初始化环境Long start = System.currentTimeMillis();String sql = "" +"insert into testdb.tuser\n" +" (name, remark, createtime, updatetime)\n" +"values\n" +" (?, ?, ?, ?)";for (int i = 0; i < m; i++) {//从池中获取连接Connection conn = myBroker.getConnection();PreparedStatement pstmt = conn.prepareStatement(sql);for (int k = 0; k < n; k++) {pstmt.setString(1, RandomToolkit.generateString(12));pstmt.setString(2, RandomToolkit.generateString(24));pstmt.setDate(3, new Date(System.currentTimeMillis()));pstmt.setDate(4, new Date(System.currentTimeMillis()));//加入批处理pstmt.addBatch();}pstmt.executeBatch(); //执行批处理// pstmt.clearBatch(); //清理批处理pstmt.close();myBroker.freeConnection(conn); //连接归池}Long end = System.currentTimeMillis();System.out.println("批量执行" + m + "*" + n + "=" + m * n + "条Insert操作,共耗时:" + (end - start) /1000f + "秒!");}public static void main(String[] args) throws Exception {init();Long start = System.currentTimeMillis();System.out.println("--------A组测试----------");testInsert();testInsertBatch(100, 1000);testInsertBatch(250, 400);testInsertBatch(400, 250);testInsertBatch(500, 200);testInsertBatch(1000, 100);testInsertBatch(2000, 50);testInsertBatch(2500, 40);testInsertBatch(5000, 20);Long end1 = System.currentTimeMillis();System.out.println("B组测试过程结束,全部测试耗时:" + (end1 - start) / 1000f + "秒!");System.out.println("--------B组测试----------");testInsert2();testInsertBatch2(100, 1000);testInsertBatch2(250, 400);testInsertBatch2(400, 250);testInsertBatch2(500, 200);testInsertBatch2(1000, 100);testInsertBatch2(2000, 50);testInsertBatch2(2500, 40);testInsertBatch2(5000, 20);Long end2 = System.currentTimeMillis();System.out.println("B组测试过程结束,全部测试耗时:" + (end2 - end1) / 1000f + "秒!");}}运行结果:--------A组测试----------单条执行100000条Insert操作,共耗时:36.766秒!批量执行100*1000=100000条Insert操作,共耗时:33.625秒!批量执行250*400=100000条Insert操作,共耗时:35.063秒!批量执行400*250=100000条Insert操作,共耗时:35.296秒!批量执行500*200=100000条Insert操作,共耗时:37.016秒!批量执行1000*100=100000条Insert操作,共耗时:35.953秒!批量执行2000*50=100000条Insert操作,共耗时:36.265秒!批量执行2500*40=100000条Insert操作,共耗时:36.625秒!批量执行5000*20=100000条Insert操作,共耗时:37.234秒!B组测试过程结束,全部测试耗时:323.906秒!--------B组测试----------单条执行100000条Insert操作,共耗时:44.188秒!批量执行100*1000=100000条Insert操作,共耗时:34.235秒!批量执行250*400=100000条Insert操作,共耗时:34.328秒!批量执行400*250=100000条Insert操作,共耗时:34.032秒!批量执行500*200=100000条Insert操作,共耗时:33.625秒!批量执行1000*100=100000条Insert操作,共耗时:34.125秒!批量执行2000*50=100000条Insert操作,共耗时:33.797秒!批量执行2500*40=100000条Insert操作,共耗时:35.359秒!批量执行5000*20=100000条Insert操作,共耗时:36.218秒!B组测试过程结束,全部测试耗时:320.0秒!上面的测试结果似乎在意料之外,看来是用连接池技术,各种执行方式性能差异不是很大。

相关文档
最新文档