2017-05-04 67 views
0

我的服務器出現性能問題。使用Java寫入MySQL數據庫的性能低下

現在這裏是設置:

我已經租了一個虛擬服務器(4 GB,2個vCores /線程)。在這臺服務器上運行一個Java程序,通過TCP連接到另一臺服務器。一旦服務器1連接到服務器2,服務器2開始連續發送數據(每分鐘約250,000行,每行約50字節的數據)。服務器1然後拆分每一行,並通過向服務器1上運行的MySQL數據庫的表中添加一行來存儲數據。好吧,所以這裏是問題:我的服務器1不能跟上。

這些是相關的Java部分。

接收數據:

InputStream in = socket.getInputStream(); 
BufferedInputStream bin = new BufferedInputStream(in); 
InputStreamReader inReader = new InputStreamReader(bin, "UTF-8"); 
BufferedReader reader = new BufferedReader(inReader); 
String line; 

... something... 

    while((line = reader.readLine())!=null) { 
     mySqlConn.WriteReferenceData(line); 
    } 
} 

一切只是直線前進。並寫入數據:

public void WriteReferenceData(String line) { 
    String[] data = line.split(";"); 
    String query = " insert into reference (field1, field2, field3, field4, field5, field6, field7, field8)" 
     + " values (?, ?, ?, ?, ?, ?, ?, ?)"; 
    try { 
     PreparedStatement preparedStmt = conn.prepareStatement(query); 
     preparedStmt.setString (1, data[0]); 
     preparedStmt.setString (2, data[1]); 
     preparedStmt.setString (3, data[2]); 
     preparedStmt.setString (4, data[3]); 
     preparedStmt.setString (5, data[4]); 
     preparedStmt.setString (6, data[5]); 
     preparedStmt.setString (7, data[6]); 
     preparedStmt.setString (8, data[7]); 
     preparedStmt.execute(); 
    } 
    catch (Exception e) { 
     ... something... 
    } 
} 

那麼我該如何提高性能?

1.)一點都沒有,因爲服務器太慢了?

2.)會使用不同的語言(例如沒有解釋器)有幫助嗎?

3.)它只是馬虎的編程嗎?

感謝您的幫助! Raphael

+2

如此多的因素可以影響:連接池缺失,未關閉的語句,每個語句的單個事務等等等等 – Andremoniy

+0

我已經回答了類似的問題,您可以在這裏查看http://stackoverflow.com/a/ 43778950/5558072您可以使用批處理語句代替 –

+0

我同意;這是(幾乎)不可能從遠程調試;基於單個SO問題。請記住:這是一個我們免費提供幫助的社區(當然,我們中的某些人的聲譽也會受益)。但是,如果您的商業產品存在這樣的問題,那麼您可能不得不硬着頭皮聘請一些知道如何快速解決此類問題的單槍打飛服務。 – GhostCat

回答

1

好吧,它確實歸結爲停止插入每一行單獨。

但是,簡單地使用批處理語句作爲YCF_L指出是不夠的。我也需要修改我的連接參數。沒有「rewriteBatchedStatements = true」,沒有性能增益。

DriverManager.getConnection("jdbc:mysql://localhost/" 
    + database + "?user=userXY&rewriteBatchedStatements=true"); 

謝謝Jan Khonski,你回答也會有效。不過,我正在對我的標記是正確的,因爲我想列舉幾種做法。

我最終放棄了批處理語句,並通過隱式關閉自動提交來使用延遲的數據庫更新。

實現此目的的一種方法是封裝一系列帶有START TRANSACTION的INSERT語句;和COMMIT;

參見MySQL Documentation。 到目前爲止,我還沒有結果表明,當數據庫變大時哪種方法運行得最好。

+1

關閉自動提交功能幾乎總是正確且性能最重要。使用準備好的語句也是必須的。然後'useServerPrepStmts = true',批處理並插入多個值。也有一些骯髒的黑客,因爲禁用完整性或刪除索引以後重建。 – maaartinus

+0

是的,我寧願有幾種方法來解決問題,所以我可以選擇最有效的方法!並感謝maaartinus提供更多關於如何提高性能的細節。 –

0

我也有這個問題。創建一個同時插入多行的SQL查詢!以編程方式做!

insert into reference (field1, field2, field3, field4, field5, field6, field7, field8)" 
    + " values (v00, v01, v02, v03, v04,v05, v06, v07), 
    (v10, v11, v12, v13, v14,v15, v16, v17) ..." 

只確保SQL查詢長度不超過允許的最大值* 65,536 *(對於不同的數據庫它可能不同)。

https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html SQL語句被預編譯並存儲在PreparedStatement對象中。然後可以使用此對象多次高效地執行此語句。

您每次創建一個新行時都會創建PreparedStatement對象!而是收集多行,然後做一個插入語句!

+0

MySQL的默認限制超過1MB,可能是16MB(不是64KB)。 100至1000行的塊是最佳的。每個塊之後有'COMMIT'。 –