关于jdbc批处理的一些小问题

一个项目实现过程中难免遇到一些批量执行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));
    }
}

首先声明一下笔者的配置:

  1. mysql5.5;
  2. jdk11;
  3. 驱动 mysql-connector-java-8.0.13.jar;
  4. CPU i5-6200U;
  5. 内存4G;

开始笔者犯了一个严重的错误,就算以为批处理会自动开启事务,最后测试结果为27秒,对此差点怀疑是假的批处理,最后抱着试一试的态度加入事务相关代码,果然如此,仅耗时不到3秒,最后结果评测:常规方式31秒,批处理不到3秒,同一个事务内不进行批处理需要4秒,好在问题是解决了,得出重要结论:批处理也要声明事务!

猜你喜欢

转载自blog.csdn.net/qq_38258310/article/details/84062913