一个项目实现过程中难免遇到一些批量执行sql语句的情况,例如执行1万条插入语句,如果使用传统的插入方式则需要建立1万次连接,一次发送一条sql语句,这样是及其浪费性能的,接下来通过三种不同的方式模拟批量的插入语句,代码如下:
package com.lsm1998.shop.test;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.Statement;
public class JDBCTest
{
static
{
try
{
//com.mysql.jdbc.Driver与com.mysql.cj.jdbc.Driver有啥不同?
//com.mysql.jdbc.Driver 是 mysql-connector-java 5中的,
//com.mysql.cj.jdbc.Driver 是 mysql-connector-java 6中的
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args) throws Exception
{
Connection connection = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8&serverTimezone=UTC", "root", "123456");
//test1(connection);
//test2(connection);
test3(connection);
}
/**
* 常规提交
* 耗时 31202ms
*
* @param connection
* @throws Exception
*/
private static void test1(Connection connection) throws Exception
{
Statement statement = connection.createStatement();
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
{
String sql = "insert into v1(name) values('测试_" + i + "');";
statement.execute(sql);
}
long end = System.currentTimeMillis();
System.out.println("耗时=" + (end - start));
statement.close();
}
/**
* 采用事务提交
* 耗时 4182ms
*
* @param connection
* @throws Exception
*/
private static void test2(Connection connection) throws Exception
{
connection.setAutoCommit(false);
Statement statement = connection.createStatement();
long start = System.currentTimeMillis();
try
{
for (int i = 0; i < 10000; i++)
{
String sql = "insert into v1(name) values('测试_" + i + "');";
statement.execute(sql);
}
connection.commit();
statement.close();
} catch (Exception e)
{
connection.rollback();
}
long end = System.currentTimeMillis();
System.out.println("耗时=" + (end - start));
}
/**
* 批处理提交
* 耗时 2634ms(预编译)
*
* @param connection
* @throws Exception
*/
private static void test3(Connection connection) throws Exception
{
connection.setAutoCommit(false);
String sql = "insert into v1(name) values(?);";
PreparedStatement ps = connection.prepareStatement(sql);
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++)
{
ps.setString(1, "测试_" + i);
ps.addBatch();
}
ps.executeBatch();
connection.commit();
long end = System.currentTimeMillis();
System.out.println("耗时=" + (end - start));
}
}
首先声明一下笔者的配置:
- mysql5.5;
- jdk11;
- 驱动 mysql-connector-java-8.0.13.jar;
- CPU i5-6200U;
- 内存4G;
开始笔者犯了一个严重的错误,就算以为批处理会自动开启事务,最后测试结果为27秒,对此差点怀疑是假的批处理,最后抱着试一试的态度加入事务相关代码,果然如此,仅耗时不到3秒,最后结果评测:常规方式31秒,批处理不到3秒,同一个事务内不进行批处理需要4秒,好在问题是解决了,得出重要结论:批处理也要声明事务!