JDBC--insert实现批量插入

本文介绍了如何通过PreparedStatement的addBatch和事务管理优化数据库插入性能,对比了逐条插入和批量插入的效率提升,展示了在Java中利用批处理和事务来加速20000条数据插入的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. 使用PreparedStatement实现批量插入的普通方法:
@Test
    public void InsertForList(){
        Connection conn = null;
        PreparedStatement ps = null;
        long start = System.currentTimeMillis();
        try {
            conn = DBUtil.connection();
            String sql = "insert into goods values (?)";
            ps=conn.prepareStatement(sql);
            for (int i=0;i<20000;i++){
                ps.setString(1,"name"+i);
                ps.executeUpdate();
            }
            long end = System.currentTimeMillis();
            System.out.println(end-start);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(conn,ps);
        }
    }

缺点是一条一条插入,需要的时间很长。
插入两万条数据:时间 19722
在这里插入图片描述

2. 优化 ------- 使用 addBatch 实现批量插入。

addBatch(String): 添加需要批量处理的SQL语句或是参数;
executeBatch(): 执行批量处理语句;
clearBatch(): 清空缓存的数据

但是要把属性文件中的 url 修改。 后面添加?rewriteBatchedStatements=true

url=jdbc:mysql://localhost:3306/mytest1?rewriteBatchedStatements=true

具体代码实现:

@Test
    public void InsertForList01(){

        Connection conn = null;
        PreparedStatement ps = null;
        long start = System.currentTimeMillis();

        try {
            conn = DBUtil.connection();
            String sql = "insert into goods values (?)";
            ps=conn.prepareStatement(sql);
            for (int i=0;i<20000;i++){
                ps.setString(1,"name"+i);
                //攒sql
                ps.addBatch();
                if(i%500==0){
                   ps.executeBatch();
                }
                ps.clearBatch();
            }
            long end = System.currentTimeMillis();
            System.out.println(end-start);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(conn,ps);
        }
    }

插入两万条数据时间: 609 很大提升
在这里插入图片描述

3、通过事务机制控制提交,进一步优化

conn.setAutoCommit(false);
执行完所有操作以后:
conn.commit();

@Test
    public void InsertForList02(){

        Connection conn = null;
        PreparedStatement ps = null;
        long start = System.currentTimeMillis();

        try {
            conn = DBUtil.connection();
            String sql = "insert into goods values (?)";
            //设置 不让其自动提交
            conn.setAutoCommit(false);
            ps=conn.prepareStatement(sql);
            for (int i=0;i<20000;i++){
                ps.setString(1,"name"+i);
                //攒sql
                ps.addBatch();
                if(i%500==0){
                    ps.executeUpdate();
                }
                ps.clearBatch();
            }
            long end = System.currentTimeMillis();
            System.out.println(end-start);
            conn.commit();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DBUtil.close(conn,ps);
        }

    }

插入两万条数据时间 562 (针对数据更多的效果更有效)
在这里插入图片描述

### Sharding-JDBC 批量插入实现方法 Sharding-JDBC 是一个用于分布式数据库的中间件,它通过对 JDBC 原生 API 的封装,在应用层面实现了分库分表等功能[^1]。为了实现批量插入操作,可以通过标准的 JDBC 批处理方式完成数据的高效写入。 以下是具体的实现说明以及代码示例: #### 依赖引入 在项目中需要先引入 `sharding-jdbc-core` 及其相关依赖。以下是一个典型的 Maven 配置片段: ```xml <dependency> <groupId>com.dangdang</groupId> <artifactId>sharding-jdbc-core</artifactId> <version>${sharding.jdbc.version}</version> </dependency> ``` 其中 `${sharding.jdbc.version}` 应替换为具体版本号,例如 `1.5.4`[^4]。 #### 分片配置 在使用 Sharding-JDBC 进行批量插入之前,需定义好分片规则(如水平分表、分库策略)。这些规则通常通过 Spring 或 YAML 文件进行配置。例如,假设我们有一个名为 `t_order` 的表按订单 ID 进行分片,则可以这样设置: ```yaml dataSources: ds_0: ... ds_1: ... shardingRule: tables: t_order: actualDataNodes: ds_${0..1}.t_order_${0..1} tableStrategy: inline: shardingColumn: order_id algorithmExpression: t_order_${order_id % 2} ``` 此配置表示 `t_order` 表会按照 `order_id` 对 2 取模的结果分布到不同的逻辑表中[^2]。 #### 批量插入代码示例 利用 JDBC 提供的批处理机制,配合 Sharding-JDBCSQL 解析能力,可轻松实现跨多个物理分片的数据插入。以下是一段 Java 示例代码: ```java import java.sql.Connection; import java.sql.PreparedStatement; public class BatchInsertExample { public static void main(String[] args) throws Exception { try (Connection connection = dataSource.getConnection()) { // 获取连接对象 String sql = "INSERT INTO t_order(order_id, user_id, status) VALUES (?, ?, ?)"; try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) { for (int i = 0; i < 100; i++) { // 插入 100 条记录作为演示 preparedStatement.setInt(1, i); // 设置 order_id preparedStatement.setInt(2, i * 10); // 设置 user_id preparedStatement.setString(3, "NEW"); // 设置状态字段 preparedStatement.addBatch(); // 将当前参数加入批处理队列 } int[] resultCounts = preparedStatement.executeBatch(); // 执行批量插入 System.out.println("受影响的行数:" + java.util.Arrays.toString(resultCounts)); } finally { connection.close(); } } } } ``` 在此代码中,`addBatch()` 方法被用来累积待执行的操作;而最终调用 `executeBatch()` 则一次性提交所有积累下来的 SQL 操作给数据库引擎去执行。 需要注意的是,虽然 Sharding-JDBC 支持复杂的 SQL 查询语法,但对于某些特殊结构比如 union 和嵌套子查询则存在局限性[^3]。不过对于基本的 DML 操作来说,它是完全兼容并优化过的。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值