2010-08-14 40 views
5

嘿,即時通訊試圖將大約60萬令牌寫入我的MySQL數據庫表。我使用的引擎是InnoDB。更新過程是永遠(所以我最好的猜測是,我完全錯過了我的代碼中的東西,而我正在做的只是簡單的愚蠢。MySQL更新正在進行中

也許某人有一個自發的想法似乎是什麼吃我的表現:

這裏是我的代碼:

public void writeTokens(Collection<Token> tokens){ 

    try{ 
     PreparedStatement updateToken = dbConnection.prepareStatement("UPDATE tokens SET `idTag`=?, `Value`=?, `Count`=?, `Frequency`=? WHERE `idToken`=?;"); 

     for (Token token : tokens) { 

      updateToken.setInt(1, 0); 
      updateToken.setString(2, token.getWord()); 
      updateToken.setInt(3, token.getCount()); 
      updateToken.setInt(4, token.getFrequency()); 
      updateToken.setInt(5, token.getNounID()); 

      updateToken.executeUpdate(); 
     } 
    }catch (SQLException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

非常感謝

回答

5

我沒有給你一個特定的Java的答案,但包住整個事情在一個事務中!如果你不這樣做,那麼MySQL(當寫入InnoDB時)就是這樣rts併爲每個更新語句提交新的事務。

只需在開始呼叫前執行START TRANSACTION,並在所有更新/插入完成後執行COMMIT。我也認爲MySQL會延遲索引更新直到事務結束,如果您更新索引字段,這應該可以大大提高性能。

+0

或這個,應該有相同的效果,數據庫明智的 – Nicolas78 2010-08-14 22:23:02

+0

這些都是很好的答案......很遺憾,我只能接受一個作爲我接受的答案,因爲真正的伎倆是所有的組合。坦克再次@所有 – evermean 2010-08-15 09:57:22

4

如果您的表中有一個或多個字段具有索引,則每個更新都會強制重建這些索引,這可能需要一段時間,因爲您接近數十萬個條目。

PreparedStatement帶有一個addBatch()方法 - 我沒有使用它,但是如果我正確地得到它,可以將幾批記錄傳輸到準備好的語句中,然後一次更新。這將索引重建次數從600.000減少到1 - 您應該感受到差異:)

3

每個更新語句都需要往返數據庫。這會給你帶來巨大的性能提升。

有一對夫婦的方式插入這個數據到數據庫中,而不執行數十萬查詢:

  • 使用批量插入(LOAD DATA INFILE)。
  • 使用一次插入多行的單個插入語句。例如,您可以爲每個插入語句插入100行。

然後,您可以使用單個更新語句將數據複製到目標表中。這將減少服務器往返次數,提高性能。