【问题标题】:Optimizing database inserts java优化数据库插入java
【发布时间】:2023-04-10 09:40:01
【问题描述】:

我对 java 和数据库比较陌生,因此请您帮助我优化代码。我有大约 20 个带有逗号分隔值的文本文件。每个文本文件有大约 10000 行基于每行中的第三个值,我将数据插入到不同的表中。每次我检查第三个值并使用不同的方法来保存这些数据。我的代码如下。有人可以告诉我这是否是执行此操作的正确方法。 提前致谢。

public  void readSave() throws SQLException
{
    File dir = new File("C:\\Users\\log");
    String url = Config.DB_URL;
    String user= Config.DB_USERNAME;
    String password= Config.DB_PASSWORD;
    con= DriverManager.getConnection(url, user, password);
    con.setAutoCommit(false);
    String currentLine;
    if (!dir.isDirectory())
        throw new IllegalStateException();
    for (File file : dir.listFiles()) {
        BufferedReader br;
        try {
            br = new BufferedReader(new FileReader(file));
            while ((currentLine = br.readLine()) != null) {
                List<String> values = Arrays.asList(currentLine.split(","));
                if (values.get(2).contentEquals("0051")) 
                    save0051(values,con);
                else if(values.get(2).contentEquals("0049"))
                    save0049(values,con);
                else if(values.get(2).contentEquals("0021"))
                    save0021(values,con);
                else if(values.get(2).contentEquals("0089"))
                    save0089(values,con);
                if(statement!=null)
                    statement.executeBatch();
            }
        } catch (FileNotFoundException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    try { 
        con.commit();
        statement.close();
        con.close();
    } 
    catch (Exception e) {}
}

private void save0051(List<String> values, Connection connection) throws SQLException {
    // TODO Auto-generated method stub
    String WRITE_DATA = "INSERT INTO LOCATION_DATA"
            + "(loc_id, timestamp, message_id" +
            ) VALUES (?,?,?)";
    try {
        statement = connection.prepareStatement(WRITE_DATA);
        statement.setString(1, values.get(0));
        statement.setLong(2, Long.valueOf(values.get(1)));
        statement.setInt(3, Integer.valueOf(values.get(2)));
        statement.addBatch();
    } catch (SQLException e) {
        e.printStackTrace();
        System.out.println("Could not save to DB, error: " + e.getMessage());
    }
    return;
}

【问题讨论】:

  • 看来你正在准备每个函数调用的语句,如果你准备一次会更好,使用不同的语句对象名称并在各种函数中访问它们

标签: java database


【解决方案1】:
【解决方案2】:

【讨论】:

    【解决方案3】:
    1. 不要在循环中创建数据库连接。这是一项昂贵的操作,您应该只创建一次。
    2. 不要在循环中创建PreparedStatement。创建一次即可重复使用。
    3. 不要在每次插入后提交。 Read about using batches for inserting。如果您只在每 200 次 INSERT 中提交一次,这将显着减少“提交开销”。

    【讨论】:

    • 我需要 4 个不同的 PreparedStatements 用于 4 个不同的表吗??
    • @user2236033 是的,因为表名是在准备好的语句中编译的,只有值是可变的。
    【解决方案4】:

    如果这对性能至关重要,我建议进行一些更改。

    1. 将连接创建移出循环,您不希望这样做数千次。
    2. 由于每个函数都重复执行相同的查询,您可以缓存 PreparedStatements,并重复执行它们,而不是在每个查询中重新创建它们。这样,数据库只需要优化一次查询,每个查询将只传输查询的数据,而不是整个查询和数据。

    【讨论】:

    • 没问题。但是,我会注意@user714965 对插入进行批处理的建议。这是明智之举。其实我更进一步说,你应该在这里检查你是否真的需要交易,如果你不需要,只需删除交易相关的代码。最后,如果您确实需要它并且您正在针对生产数据库运行它,那么限制您的插入速度可能是一个好主意,这样您就不会因为高写入工作负载而丢掉数据库。
    • 感谢您的更新。按照建议,我移动了连接创建和
    • 在插入 4 个不同的表并将其作为参数传递给每个方法时,是否需要 4 个不同的 PrepareStatements?
    猜你喜欢
    • 2012-03-07
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-09
    • 2013-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多