优化数据库插入java

问题描述:

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

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; 
} 
+1

看来你正准备在每个函数调用语句,会更好,如果你准备他们一次,用不同的语句对象的名字,只是访问了它们在varous功能 – Akash 2013-05-02 13:14:05

  1. 不要建立在循环的数据库连接。这是一项昂贵的操作,您只应创建一次。
  2. 不要在循环中创建PreparedStatement。创建一次并重用它。
  3. 不要在每个INSERT后提交。 Read about using batches for inserting。这大大降低了“提交开销”,如果你只提交一个提交数据,比如200个INSERT。
+0

我需要4 4个不同的表的不同PreparedStatements? – 2013-05-03 07:00:58

+0

@ user2236033是的,你这样做是因为表名是在准备语句中编译的,只有值是可变的。 – Kai 2013-05-03 07:38:07

如果这将是性能至关重要,我会建议一些更改。

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

感谢您的发贴 – 2013-05-02 13:27:21

+0

没问题。然而,我会留意@ user714965关于批量插入的建议。这是明智的做法。事实上,我会进一步说,你应该检查你是否真的需要交易,如果你不需要它,只需删除交易相关的代码。 最后,如果您确实需要这个,并且您正在对生产数据库运行它,那么对插入进行速率限制可能是一个好主意,因此您不会因高写入工作量而抛弃数据库。 – 2013-05-02 13:31:03

+0

感谢您的更新。正如所建议的,我移动了连接创建和 – 2013-05-03 06:16:41