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

当前实现由如下条件:

  执行数据库:Mysql

执行数据数量:10万条

执行前提:执行差入数据库钱均需要提供空表,防止数据量大造成的影响

执行方式:Statement和PreparedStatement两种方式

执行步骤开始:

1、创建表

 CREATE TABLE T_PRODUCT (
ID bigint(12) NOT NULL AUTO_INCREMENT COMMENT '主键',
NAME varchar(60) NOT NULL COMMENT '产品名称',
WEIGHT varchar(60) NOT NULL COMMENT '产品重量',
MARK varchar(60) NOT NULL COMMENT '产品说明',
PRIMARY KEY (ID)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='产品表';

2、编写操作数据库工具类

 package com.luwei.test.jdbc;

 import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ResourceBundle; /**
* <Description> TODO<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2017年1月9日 <br>
* @since V1.0<br>
* @see com.luwei.test.jdbc <br>
*/
public class JdbcTemplate {
private static String DRIVER_CLASS_NAME = null;
private static String URL = null;
private static String USERNAME = null;
private static String PASSWORD = null; static {
ResourceBundle bundle = ResourceBundle.getBundle("jdbc");
DRIVER_CLASS_NAME = bundle.getString("jdbc.driverClassName");
URL = bundle.getString("jdbc.url");
USERNAME = bundle.getString("jdbc.username");
PASSWORD = bundle.getString("jdbc.password");
} /**
*
* <Description> 获取数据库连接<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2017年1月9日 下午10:19:41 <br>
* @return
* @throws Exception
* <br>
*/
public static Connection getConnection() throws Exception {
Class.forName(DRIVER_CLASS_NAME);
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
return connection;
} /**
*
* <Description> 提交事务<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2017年1月9日 下午10:20:48 <br>
* @param connection
* <br>
*/
public static void commit(Connection connection) {
try {
connection.commit();
}
catch (SQLException e) {
e.printStackTrace();
}
} /**
*
* <Description> 开启事务<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2017年1月9日 下午10:23:56 <br>
* @param connection
* <br>
*/
public static void beginTx(Connection connection) {
try {
connection.setAutoCommit(false);
}
catch (SQLException e) {
e.printStackTrace();
}
} /**
*
* <Description> 回滚<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2017年1月9日 下午10:24:33 <br>
* @param connection
* <br>
*/
public static void rollback(Connection connection) {
try {
connection.rollback();
}
catch (SQLException e) {
e.printStackTrace();
}
} /**
*
* <Description> TODO<br>
*
* @author lu.wei<br>
* @email 1025742048@qq.com <br>
* @date 2017年1月9日 下午10:28:49 <br>
* @param statement
* @param connection
* <br>
*/
public static void releaseDb(Statement statement, Connection connection) {
try {
statement.close();
connection.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
}

3、执行数据库插入操作

3.1、使用Statement直接插入,三次执行耗时:41979 42608 42490

 @Test
public void testStatement() {
Connection connection = null;
Statement statement = null;
try {
connection = JdbcTemplate.getConnection();
JdbcTemplate.beginTx(connection); statement = connection.createStatement();
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
String sql = "insert into t_product values(null,'name_" + i + "','120kg','mark_" + i + "')";
statement.execute(sql);
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
JdbcTemplate.commit(connection);
}
catch (Exception e) {
e.printStackTrace();
JdbcTemplate.rollback(connection);
}
finally {
JdbcTemplate.releaseDb(statement, connection);
}
}

3.2、使用PreparedStatement直接插入,三次执行耗时:22808 24675 22281

 @Test
public void testPreparedStatement() {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = JdbcTemplate.getConnection();
JdbcTemplate.beginTx(connection);
String sql = "insert into t_product values(null,?,?,?)"; statement = connection.prepareStatement(sql);
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
statement.setString(1, "name_" + i);
statement.setString(2, "120kg");
statement.setString(3, "mark_" + i);
statement.executeUpdate();
}
long end = System.currentTimeMillis();
System.out.println(end - begin);
JdbcTemplate.commit(connection);
}
catch (Exception e) {
e.printStackTrace();
JdbcTemplate.rollback(connection);
}
finally {
JdbcTemplate.releaseDb(statement, connection);
}
}

3.3、使用BatchStatement直接插入,三次执行耗时:15342 15235 15485

 @Test
public void testBatchStatement() {
Connection connection = null;
Statement statement = null;
try {
connection = JdbcTemplate.getConnection();
JdbcTemplate.beginTx(connection); statement = connection.createStatement();
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
String sql = "insert into t_product values(null,'name_" + i + "','120kg','mark_" + i + "')";
statement.addBatch(sql); if ((i + 1) % 100 == 0) {
statement.executeBatch();
statement.clearBatch();
}
}
statement.executeBatch();
statement.clearBatch();
long end = System.currentTimeMillis();
System.out.println(end - begin);
JdbcTemplate.commit(connection);
}
catch (Exception e) {
e.printStackTrace();
JdbcTemplate.rollback(connection);
}
finally {
JdbcTemplate.releaseDb(statement, connection);
}
}

3.4、使用BatchPreparedStatement直接插入,三次执行耗时:21913 22045 23291

 @Test
public void testBatchPreparedStatement() {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = JdbcTemplate.getConnection();
JdbcTemplate.beginTx(connection);
String sql = "insert into t_product values(null,?,?,?)"; statement = connection.prepareStatement(sql);
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
statement.setString(1, "name_" + i);
statement.setString(2, "120kg");
statement.setString(3, "mark_" + i);
statement.addBatch();
if ((i + 1) % 100 == 0) {
statement.executeBatch();
statement.clearBatch();
}
}
statement.executeBatch();
statement.clearBatch();
long end = System.currentTimeMillis();
System.out.println(end - begin);
JdbcTemplate.commit(connection);
}
catch (Exception e) {
e.printStackTrace();
JdbcTemplate.rollback(connection);
}
finally {
JdbcTemplate.releaseDb(statement, connection);
}
}

3.5、使用采用多Value值Statement直接插入,三次执行耗时:2931 3007 3203 2964

 @Test
public void testMutilValueStatement() {
Connection connection = null;
Statement statement = null;
try {
connection = JdbcTemplate.getConnection();
JdbcTemplate.beginTx(connection); statement = connection.createStatement(); StringBuffer sql = new StringBuffer("insert into t_product values");
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
if (i != 0) {
sql.append(",");
}
sql.append("(null,'name_" + i + "','120kg','mark_" + i + "')");
}
statement.execute(sql.toString());
long end = System.currentTimeMillis();
System.out.println(end - begin);
JdbcTemplate.commit(connection);
}
catch (Exception e) {
e.printStackTrace();
JdbcTemplate.rollback(connection);
}
finally {
JdbcTemplate.releaseDb(statement, connection);
}
}

3.6、使用采用多Value值PreparedStatement直接插入,三次执行耗时:3356 3218 3233

 @Test
public void testMutilValuePreparedStatement() {
Connection connection = null;
PreparedStatement statement = null;
try {
connection = JdbcTemplate.getConnection();
JdbcTemplate.beginTx(connection); StringBuffer sql = new StringBuffer("insert into t_product values");
long begin = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
if (i != 0) {
sql.append(",");
}
sql.append("(null,'name_" + i + "','120kg','mark_" + i + "')");
}
statement = connection.prepareStatement(sql.toString());
statement.executeUpdate();
long end = System.currentTimeMillis();
System.out.println(end - begin);
JdbcTemplate.commit(connection);
}
catch (Exception e) {
e.printStackTrace();
JdbcTemplate.rollback(connection);
}
finally {
JdbcTemplate.releaseDb(statement, connection);
}
}

通过以上时间结果得出如下数据表格:

总结:通过如上的数据对比发现

  1、PreparedStatement执行数据库插入比使用Statement执行数据库插入明显有性能优势,原因归功于PreparedStatement能够预先对SQL进行编译,做到执行时进行SQL共享

  2、执行数据库批量操作是使用Batch方式对数据库采用批次操作能够明显提升数据库操作性能能

  3、不管是直接多次插入数据库还是采用Batch方式执行数据库的插入,均会发送多次SQL脚本去执行,这样明显没有发送一次SQL脚本执行来的效率高

  4、采用单SQL执行数据库批量操作时Statement对比PreparedStatement有微弱的优势,可能是Statement不需要判断注参的原因吧

JDBC批量插入数据效率分析的更多相关文章

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

    JDBC批量插入数据优化,使用addBatch和executeBatch SQL的批量插入的问题,如果来个for循环,执行上万次,肯定会很慢,那么,如何去优化呢? 解决方案:用 preparedSta ...

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

    平时使用mysql插入.查询数据都没有注意过效率,今天在for循环中使用JDBC插入1000条数据居然等待了一会儿 就来探索一下JDBC的批量插入语句对效率的提高 首先进行建表 create tabl ...

  3. android批量插入数据效率对比

    对比在android中批量插入数据的3中方式对比(各插入1W条数据所花费的时间): 1. 一个一个插入 /** * 向表中插入数据 * * @param openHelper * @param app ...

  4. 【实践】jdbc批量插入数据

    参考文献:http://my.oschina.net/u/1452675/blog/203670 http://superjavason.iteye.com/blog/255423 /*测试批量写入数 ...

  5. jdbc批量插入数据

    //插入很多书(批量插入用法) public void insertBooks(List<Book> book) {   final List<Book> tempBook=b ...

  6. Java使用JDBC连接数据库逐条插入数据、批量插入数据、以及通过SQL语句批量导入数据的效率对比

    测试用的示例java代码: package com.zifeiy.test.normal; import java.io.File; import java.io.FileOutputStream; ...

  7. 向mysql中批量插入数据的性能分析

    MYSQL批量插入数据库实现语句性能分析 假定我们的表结构如下 代码如下   CREATE TABLE example (example_id INT NOT NULL,name VARCHAR( 5 ...

  8. JDBC(五)—— 批量插入数据

    批量插入数据 @Test public void testInsert() throws Exception { Connection conn = null; PreparedStatement p ...

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

    转自http://www.cnblogs.com/fnz0/p/5713102.html 不知道自己什么时候才有这种钻研精神- -. 1      背景 系统中需要批量生成单据数据到数据库表,所以采用 ...

随机推荐

  1. Android Configuration change引发的问题及解决方法

    之前在学习Fragment和总结Android异步操作的时候会在很多blog中看到对Configuration Change的讨论,以前做的项目都是固定竖屏的,所以对横竖屏切换以及横竖屏切换对程序有什 ...

  2. Android UI WebView的使用:

    Android UI WebView的使用: /** * @author smiling * @date 2016/10 */ 布局: <?xml version="1.0" ...

  3. VNC-Server installation on CentOS 7

    参考资料: https://www.howtoforge.com/vnc-server-installation-on-centos-7 https://linux.cn/article-5335-1 ...

  4. nyoj 756 重建二叉树

    重建二叉树主要是给你一颗二叉树的前序遍历的结果和中序遍历的结果或者后序遍历的结果或者中序遍历的结果,让你求出其中的后序遍历的结果或者前序遍历的结果,这里知道其中的两个就能求出第三个,但是知道的两个必须 ...

  5. 窗口 对话框 Pop Dialog 示例

    两者的区别 PopupWindow和AlertDialog最大的区别: AlertDialog是非阻塞线程的,AlertDialog弹出的时候,后台可以做其他事情(也即弹出对话框后程序会继续向下执行) ...

  6. webform 复杂点的服务器控件

    1  , dropdownlist:  下拉框 属性items  列表集合,  里面的每一个元素是一个 listitem . 联动的时候注意要 设置属性 .Autopostback 为ture: 注注 ...

  7. c# 字符串编码问题

    一. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出256种状态,这被称为一个字节(byte). ...

  8. php代码结尾不要添加结尾标记

    如果文件内容是纯 PHP 代码,最好在文件末尾删除 PHP 结束标记.这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符,会导致 PHP 开始输出这些空白,而脚本中此时并无输出的意图.

  9. Design Pattern ——Factory Method&Abstract Factory

    今天开始复习设计模式.设计模式相关的资料有很多,概念性的东西就画个图就可以了.把关注点放在例子上,设计模式还是要使用中才有感受. 从Factory Method&Abstract Factor ...

  10. maven发布时在不同的环境使用不同的配置文件

    在开发时,不同的环境总会使用到不同的配置.如本地,测试,预发布,发布等环境,像数据库这些都要使用到不同的配置.如果手动改的话肯定会十分的麻烦. 还好maven提供的功能能够帮我们解决这个问题. 我们通 ...