2013-05-02 47 views
0

我對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

回答

4
  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

3

如果這將是性能至關重要,我會建議一些更改。

  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