实现层次1:使用PreparedStatment一行行插入
public static void InsertTypeOne(int rows) {
// 一行行插入
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.GetConnection();
String sqlstr = "insert into user_info(name,email)values(?,?)";
ps = conn.prepareStatement(sqlstr);
for (int i = 1; i <= rows; i++) {
ps.setObject(1, "name_" + i);
ps.setObject(2, i + "@gmail.com");
ps.execute();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseResource(conn, ps);
}
}
实现层次2:使用addBatch(),executeBatch(),clearBatch()攒一波批量插入
public static void InsertTypeTwo(int rows) {
// 使用addBatch(),executeBatch(),clearBatch() 批量插入数据
// mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
// ?rewriteBatchedStatements=true 写在配置文件的url后面
// 如之前是 jdbc:mysql://localhost:3306/stock?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
// 更新为 jdbc:mysql://localhost:3306/stock?rewriteBatchedStatements=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.GetConnection();
String sqlstr = "insert into user_info(name,email)values(?,?)";
ps = conn.prepareStatement(sqlstr);
for (int i = 1; i <= rows; i++) {
ps.setObject(1, "name_" + i);
ps.setObject(2, i + "@gmail.com");
// 1. 攒sql
ps.addBatch();
if (i % 500 == 0){
// 2. 攒一批执行一次
ps.executeBatch();
// 3. 执行后要清空一下
ps.clearBatch();
}else if (i == rows){
ps.executeBatch();
ps.clearBatch();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseResource(conn, ps);
}
}
实现层次3:在2的基础上,关闭自动提交
public static void InsertTypeThree(int rows) {
// 插入数据时先禁止自动提交,数据全部execute后,再进行提交,最后再恢复自动提交
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.GetConnection();
// 1. 设置不自动提交数据
conn.setAutoCommit(false);
String sqlstr = "insert into user_info(name,email)values(?,?)";
ps = conn.prepareStatement(sqlstr);
for (int i = 1; i <= rows; i++) {
ps.setObject(1, "name_" + i);
ps.setObject(2, i + "@gmail.com");
// 1. 攒sql
ps.addBatch();
if (i % 500 == 0) {
// 2. 攒一批执行一次
ps.executeBatch();
// 3. 执行后要清空一下
ps.clearBatch();
} else if (i == rows) {
ps.executeBatch();
ps.clearBatch();
}
}
// 2. 提交数据
conn.commit();
// 3. 提交完再设置自动提交
conn.setAutoCommit(true);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseResource(conn, ps);
}
}
在本地测试时,效率如下:
public static void main(String[] args) {
int rows = 20000;
long tstart = System.currentTimeMillis();
// InsertTypeOne(rows);// 插入 20000 行数据,共耗时 41748
// InsertTypeTwo(rows);// 插入 20000 行数据,共耗时 904
InsertTypeThree(rows);// 插入 20000 行数据,共耗时 846
long tend = System.currentTimeMillis();
System.out.println("插入 " + rows + " 行数据,共耗时 " + (tend - tstart));
}
其中,方式3在数据量增大的情况下,是会有明显地效率提升。这里只使用了2万行数据,体现得不明显。
package batchinsert;
import utils.JDBCUtils;
import java.sql.Connection;
import java.sql.PreparedStatement;
public class BatchInsert {
public static void main(String[] args) {
int rows = 20000;
long tstart = System.currentTimeMillis();
// InsertTypeOne(rows);// 插入 20000 行数据,共耗时 41748
// InsertTypeTwo(rows);// 插入 20000 行数据,共耗时 904
InsertTypeThree(rows);// 插入 20000 行数据,共耗时 846
long tend = System.currentTimeMillis();
System.out.println("插入 " + rows + " 行数据,共耗时 " + (tend - tstart));
}
public static void InsertTypeOne(int rows) {
// 一行行插入
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.GetConnection();
String sqlstr = "insert into user_info(name,email)values(?,?)";
ps = conn.prepareStatement(sqlstr);
for (int i = 1; i <= rows; i++) {
ps.setObject(1, "name_" + i);
ps.setObject(2, i + "@gmail.com");
ps.execute();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseResource(conn, ps);
}
}
public static void InsertTypeTwo(int rows) {
// 使用addBatch(),executeBatch(),clearBatch() 批量插入数据
// mysql服务器默认是关闭批处理的,我们需要通过一个参数,让mysql开启批处理的支持。
// ?rewriteBatchedStatements=true 写在配置文件的url后面
// 如之前是 jdbc:mysql://localhost:3306/stock?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
// 更新为 jdbc:mysql://localhost:3306/stock?rewriteBatchedStatements=true&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.GetConnection();
String sqlstr = "insert into user_info(name,email)values(?,?)";
ps = conn.prepareStatement(sqlstr);
for (int i = 1; i <= rows; i++) {
ps.setObject(1, "name_" + i);
ps.setObject(2, i + "@gmail.com");
// 1. 攒sql
ps.addBatch();
if (i % 500 == 0) {
// 2. 攒一批执行一次
ps.executeBatch();
// 3. 执行后要清空一下
ps.clearBatch();
} else if (i == rows) {
ps.executeBatch();
ps.clearBatch();
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseResource(conn, ps);
}
}
public static void InsertTypeThree(int rows) {
// 插入数据时先禁止自动提交,数据全部execute后,再进行提交,最后再恢复自动提交
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtils.GetConnection();
// 1. 设置不自动提交数据
conn.setAutoCommit(false);
String sqlstr = "insert into user_info(name,email)values(?,?)";
ps = conn.prepareStatement(sqlstr);
for (int i = 1; i <= rows; i++) {
ps.setObject(1, "name_" + i);
ps.setObject(2, i + "@gmail.com");
// 1. 攒sql
ps.addBatch();
if (i % 500 == 0) {
// 2. 攒一批执行一次
ps.executeBatch();
// 3. 执行后要清空一下
ps.clearBatch();
} else if (i == rows) {
ps.executeBatch();
ps.clearBatch();
}
}
// 2. 提交数据
conn.commit();
// 3. 提交完再设置自动提交
conn.setAutoCommit(true);
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.CloseResource(conn, ps);
}
}
}