杰瑞科技汇

Java MySQL批量插入如何优化性能?

Java MySQL 批量插入实现指南

在Java中实现MySQL批量插入有几种高效的方法,可以显著提高数据插入性能,以下是几种常见的实现方式:

Java MySQL批量插入如何优化性能?-图1
(图片来源网络,侵删)

使用PreparedStatement的addBatch()和executeBatch()

这是最常用的批量插入方法,比单条插入性能高很多。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class BatchInsertExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/your_database";
        String user = "username";
        String password = "password";
        String sql = "INSERT INTO your_table (column1, column2, column3) VALUES (?, ?, ?)";
        try (Connection conn = DriverManager.getConnection(url, user, password);
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            // 关闭自动提交,提高性能
            conn.setAutoCommit(false);
            // 添加批量数据
            for (int i = 0; i < 1000; i++) {
                pstmt.setString(1, "value1_" + i);
                pstmt.setInt(2, i);
                pstmt.setString(3, "value3_" + i);
                pstmt.addBatch();
                // 每100条执行一次批量插入,避免内存占用过大
                if (i % 100 == 0) {
                    pstmt.executeBatch();
                }
            }
            // 执行剩余的批量
            pstmt.executeBatch();
            // 提交事务
            conn.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

使用LOAD DATA INFILE(最高效的方法)

对于大量数据插入,LOAD DATA INFILE是最快的方法,比批量插入快20-100倍。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
public class LoadDataInfileExample {
    public static void main(String[] args) {
        String url = "jdbc:mysql://localhost:3306/your_database";
        String user = "username";
        String password = "password";
        // 创建临时CSV文件
        File csvFile = new File("temp_data.csv");
        try (FileWriter writer = new FileWriter(csvFile)) {
            // 写入CSV头(可选)
            writer.write("column1,column2,column3\n");
            // 写入数据
            for (int i = 0; i < 10000; i++) {
                writer.write(String.format("value1_%d,%d,value3_%d\n", i, i, i));
            }
            // 使用JDBC执行LOAD DATA INFILE
            try (Connection conn = DriverManager.getConnection(url, user, password);
                 Statement stmt = conn.createStatement()) {
                String loadSql = String.format(
                    "LOAD DATA LOCAL INFILE '%s' INTO TABLE your_table " +
                    "FIELDS TERMINATED BY ',' " +
                    "LINES TERMINATED BY '\n' " +
                    "IGNORE 1 ROWS", // 如果有头行,忽略第一行
                    csvFile.getAbsolutePath()
                );
                stmt.execute(loadSql);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 删除临时文件
            csvFile.delete();
        }
    }
}

使用JPA/Hibernate的批量插入

如果使用JPA/Hibernate,可以通过以下方式实现批量插入:

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
public class JpaBatchInsertExample {
    @PersistenceContext
    private EntityManager entityManager;
    public void batchInsert(List<Entity> entities) {
        entityManager.getTransaction().begin();
        for (int i = 0; i < entities.size(); i++) {
            entityManager.persist(entities.get(i));
            // 每20条刷新一次上下文
            if (i % 20 == 0) {
                entityManager.flush();
                entityManager.clear();
            }
        }
        entityManager.getTransaction().commit();
    }
}

性能优化建议

  1. 调整批量大小:通常100-1000条为一个批量大小较合适
  2. 关闭自动提交:手动控制事务提交
  3. 使用连接池:如HikariCP提高连接性能
  4. 调整MySQL参数
    • innodb_buffer_pool_size
    • innodb_log_file_size
    • bulk_insert_buffer_size
  5. 考虑并行处理:对于超大数据集,可以分片并行插入

注意事项

  1. 对于LOAD DATA INFILE,需要确保MySQL服务器有访问临时文件的权限
  2. 大批量插入时注意内存使用,避免一次性加载过多数据
  3. 考虑使用事务隔离级别,避免锁竞争
  4. 在生产环境中,建议先在小数据集上测试性能

选择哪种方法取决于你的具体需求、数据量和性能要求,对于大多数应用场景,PreparedStatement的批量插入已经足够高效。

Java MySQL批量插入如何优化性能?-图2
(图片来源网络,侵删)
分享:
扫描分享到社交APP
上一篇
下一篇