2017-05-04 4 views
0

私のサーバでパフ​​ォーマンスの問題があります。Javaを使用したMySQLデータベースへの低性能書き込み

私は、仮想サーバーを借りてきた(4 GB、2 vCores /スレッド):

は今ここにセットアップです。このサーバー上では、TCPを介して第2のサーバーに接続するJavaプログラムを実行します。サーバ1がサーバ2に接続すると、サーバ2は連続的にデータを送信し始めます(1分あたり約250,000行、各行は約50バイトのデータ)。サーバ1は、各行を分割し、サーバ1上で動作するMySQLデータベースのテーブルに行を追加してデータを格納します。

これは関連する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

[OK]をクリックすると、実際には各行を別々に挿入するのが止まってしまいました。

しかし、YCF_Lとして指摘されているバッチステートメントを使用するだけでは不十分です。また、接続パラメータも変更する必要がありました。 "rewriteBatchedStatements = true"を指定しないと、パフォーマンスが向上しませんでした。

Jan Khonskiさんにお答えいただき、ありがとうございます。しかし、私は私がそれを行ういくつかの方法を挙げたいと思うほど正確であるとマークしています。

バッチ・ステートメントを破棄し、暗黙的に自動コミットをオフにしてデータベースの更新を遅延させました。

これを達成する1つの方法は、一連のINSERT文をSTART TRANSACTIONでカプセル化することです。コミット。

MySQL Documentationを参照してください。 これまでのところ、データベースが大きくなったときにどのメソッドが最適に実行されるかについての結果はありません。

+1

自動コミットをオフにすることは、ほとんどの場合常に正しく、パフォーマンスにとって重要です。準備されたステートメントを使用することも必須です。次に 'useServerPrepStmts = true'をバッチ処理し、複数の値を挿入します。整合性を無効にしたり、インデックスを削除して後で再構築したりするような不正なハッキングもあります。 – maaartinus

+0

うん、問題を解決する方法がいくつかある方が好きなので、最も効果的な方法を選ぶことができます。パフォーマンスを向上させる方法の詳細については、maartinusに感謝します。 –

0

この問題もありました。同時に複数の行を挿入する1つの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クエリの長​​さが最大65536 *を超えないようにしてください(データベースごとに異なる可能性があります)。

https://docs.oracle.com/javase/7/docs/api/java/sql/PreparedStatement.html SQLステートメントはプリコンパイルされ、PreparedStatementオブジェクトに格納されます。このオブジェクトは、このステートメントを効率的に複数回実行するために使用できます。

新しい行が来るたびにPreparedStatementオブジェクトを作成します。代わりに、複数の行を収集し、1つの挿入文を作成してください!

+0

MySQLのデフォルトの制限は1MBを超え、おそらく16MB(64KBではなく)です。 100〜1000行のチャンクが最適です。各チャンクの後に 'COMMIT'を返します。 –

関連する問題