老师,关于批处理的疑问
# 1、prepareStatement 也可以放在for循环外吧?我放在外面也可以执行呢?
2、我把prepareStatement放在for循环内还是循环外,以及是否进行批处理,分开4种情况进行了测试,测试结果如下图,对结果有些疑问。
(1)未进行批处理时,prepareStatement在循环外所花费的时间远小于在循环内所花费的时间,这节省的时间是否是因为prepareStatement在循环内时,需要创建10万个prepareStatement对象,而放在循环外时,则仅创建一个对象,所以节省了大量的创建对象花费的时间?
(2)prepareStatement放在循环外时,进行批处理与未进行批处理所花费的时间比较接近,这个是为什么呢?循环内直接executeUpdate() 与 循环内添加addBatch()再循环外executeBatch(),这两种方式执行的具体原理是什么呢?
(3) 为什么在进行批处理时,把preparestatement放在循环内比放在循环外花费的时间少呢?
package review;
import java.sql.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Scanner;
public class insert {
public static void tc1(){
long startTime=new java.util.Date().getTime();
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/jdbc?useSSl=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
connection = DriverManager.getConnection(url, "root", "root");
connection.setAutoCommit(false);
String sql = "insert into goods(id,name,price,desp) values(?,?,?,?)";
for(int i=10000;i<110000;i++) {
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,i);
preparedStatement.setString(2,"员工"+i);
preparedStatement.setFloat(3,i);
preparedStatement.setString(4, "描述" + i);
preparedStatement.executeUpdate();
}
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
if(connection!=null&!connection.isClosed()) {
connection.rollback();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
finally {
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
long endTime=new java.util.Date().getTime();
long time=endTime-startTime;
System.out.println("未批处理,prepareStatement在循环内,花费时间:"+time);
}
public static void tc2(){
long startTime=new java.util.Date().getTime();
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/jdbc?useSSl=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
connection = DriverManager.getConnection(url, "root", "root");
connection.setAutoCommit(false);
String sql = "insert into goods(id,name,price,desp) values(?,?,?,?)";
preparedStatement = connection.prepareStatement(sql);
for(int i=110000;i<210000;i++) {
preparedStatement.setInt(1,i);
preparedStatement.setString(2,"员工"+i);
preparedStatement.setFloat(3,i);
preparedStatement.setString(4, "描述" + i);
preparedStatement.executeUpdate();
}
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
if(connection!=null&!connection.isClosed()) {
connection.rollback();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
finally {
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
long endTime=new java.util.Date().getTime();
long time=endTime-startTime;
System.out.println("未批处理,prepareStatement在循环外,花费时间:"+time);
}
public static void tc3(){
long startTime=new java.util.Date().getTime();
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/jdbc?useSSl=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
connection = DriverManager.getConnection(url, "root", "root");
connection.setAutoCommit(false);
String sql = "insert into goods(id,name,price,desp) values(?,?,?,?)";
preparedStatement = connection.prepareStatement(sql);
for(int i=210000;i<310000;i++) {
preparedStatement.setInt(1,i);
preparedStatement.setString(2,"员工"+i);
preparedStatement.setFloat(3,i);
preparedStatement.setString(4, "描述" + i);
preparedStatement.addBatch();
// preparedStatement.executeUpdate();
}
preparedStatement.executeBatch();
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
if(connection!=null&!connection.isClosed()) {
connection.rollback();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
finally {
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
long endTime=new java.util.Date().getTime();
long time=endTime-startTime;
System.out.println("批处理,prepareStatement在循环外,花费时间:"+time);
}
public static void tc4(){
long startTime=new java.util.Date().getTime();
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/jdbc?useSSl=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
connection = DriverManager.getConnection(url, "root", "root");
connection.setAutoCommit(false);
String sql = "insert into goods(id,name,price,desp) values(?,?,?,?)";
for(int i=310000;i<410000;i++) {
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setInt(1,i);
preparedStatement.setString(2,"员工"+i);
preparedStatement.setFloat(3,i);
preparedStatement.setString(4, "描述" + i);
preparedStatement.addBatch();
// preparedStatement.executeUpdate();
}
preparedStatement.executeBatch();
connection.commit();
} catch (Exception e) {
e.printStackTrace();
try {
if(connection!=null&!connection.isClosed()) {
connection.rollback();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
finally {
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (connection != null && !connection.isClosed()) {
connection.close();
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
long endTime=new java.util.Date().getTime();
long time=endTime-startTime;
System.out.println("批处理,prepareStatement在循环内,花费时间:"+time);
}
public static void main(String[] args) {
tc1();
tc2();
tc3();
tc4();
}
}
正在回答
同学你好,如果将preparedStatement定义在循环内,实际添加的只有最后一条数据,并不是批量添加,如:
执行结果数量查询,tc3()方法的100000条数据,加上原有的4条数据,以及tc4()方法的最后一条数据,最后查询结果是100005条数据。
这里的的消耗是指执行sql语句时,链接数据库和写入数据以及线程执行的消耗。
祝学习愉快~
同学你好,1. 是的,prepareStatement可以在循环外。
2. 同学理解是正确的。
3. 执行时间并不是固定的,可能与电脑性能以及环境有所联系,所以会有一些差异。如下图所示:
4. 两种方式实现的原理:
addBatch()把若干sql语句装载到一起,然后一次送到数据库执行,执行需要很短的时间,而pstmt.executeUpdate() 是一条一条发往数据库执行的 时间都消耗在数据库连接的传输上面。如:
我这有一台超大功率的面粉加工机,前者相当于 把所有农户袋装的麦子收集起来用卡车一次送往加工厂 后者相当于农户排好队用同样的卡车一人一人的往加工厂送麦子 麦子加工5分钟完成,但是每个人到工厂就得3小时,我数据库执行效率再高也没用,时间都耗在传输的路上了!!
这就出现了数据传输的性能瓶颈 addBatch就是为解决这样的问题而产生的!
5. 在批处理时,在循环外定义preparedstatement,消耗会比较大,导致时间长,而在循环内定义消耗少,所以时间会比较短。如:在循环外是一次性跑一万米,而循环内就是分开跑一万米(如:一次跑一百米,最后整合到一起所以消耗少)。
- 参与学习 人
- 提交作业 9393 份
- 解答问题 16556 个
综合就业常年第一,编程排行常年霸榜,无需脱产即可学习,北上广深月薪过万 无论你是未就业的学生还是想转行的在职人员,不需要基础,只要你有梦想,想高薪
了解课程
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星