- - PR -
java.sql.Statementとjava.sql.PreparedStatementについての性能テスト
1
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2006-11-19 13:58
java.sql.Statement と java.sql.PreparedStatementについて性能テストをしているのですが、どうも思った結果が出ずに困っております。私の予想では、PreparedStatementの実行時間がStatementの1/3程度になると期待していたのですが、Statementの方が早く実行できている状況です。
もしテストの仕方、ミスコーディングがありましたらご指摘いただけないでしょうか?どうぞよろしくお願いします。 [テスト条件] MySQLのテーブルに10,000件のレコードがあり、1000回のSELECTクエリを10セットプログラムから行う。StatementとPreparedStatementクラスそれぞれに対して実施する。 [ソース] /** * Simple select preformance test. */ public void select() { // Get connection and create statement. Connection con = getConnection(); Statement stmt = null; PreparedStatement pstmt = null; int numberOfSQL = 1000; int numberOfTests = 10; long startTime = 0; long endTime = 0; long totalTime = 0; float averageTime = 0.0F; try { // Statement Test. System.out.println("Test Statement..."); for(int j=0;j<numberOfTests;j++){ startTime = System.currentTimeMillis(); for(int i=0;i<numberOfSQL;i++){ String sql1 = "SELECT id FROM table WHERE value2="+i; stmt = con.createStatement(); stmt.executeQuery(sql1); } endTime = System.currentTimeMillis(); System.out.println("Time: " + (endTime-startTime) + " miliseconds"); totalTime += (endTime-startTime); } averageTime = (float)(totalTime/numberOfTests); System.out.println("Total Time: " + totalTime + " miliseconds"); System.out.println("Average Time: " + averageTime + " miliseconds"); // PreparedStatement Test. totalTime = 0; System.out.println("Test PreparedStatement..."); for(int j=0;j<numberOfTests;j++){ startTime = System.currentTimeMillis(); String sql2 = "SELECT id FROM table WHERE value2=?"; pstmt = con.prepareStatement(sql2); for(int i=0;i<numberOfSQL;i++){ pstmt.setInt(1,i); pstmt.executeQuery(); } endTime = System.currentTimeMillis(); System.out.println("Time: " + (endTime-startTime) + " miliseconds"); totalTime += (endTime-startTime); } averageTime = (float)(totalTime/numberOfTests); System.out.println("Total Time: " + totalTime + " miliseconds"); System.out.println("Average Time: " + averageTime + " miliseconds"); } catch (Exception e) { e.printStackTrace(); } finally { try { if(stmt!=null) stmt.close(); if(pstmt!=null) pstmt.close(); if(con!=null) con.close(); } catch (Exception e) { e.printStackTrace(); } } } [結果] Test Statement... Time: 5596 miliseconds Time: 230 miliseconds Time: 144 miliseconds Time: 100 miliseconds Time: 139 miliseconds Time: 100 miliseconds Time: 95 miliseconds Time: 161 miliseconds Time: 92 miliseconds Time: 98 miliseconds Total Time: 6755 miliseconds Average Time: 675.0 miliseconds Test PreparedStatement... Time: 5398 miliseconds Time: 5220 miliseconds Time: 5186 miliseconds Time: 5201 miliseconds Time: 5175 miliseconds Time: 5201 miliseconds Time: 5189 miliseconds Time: 5171 miliseconds Time: 5190 miliseconds Time: 5181 miliseconds Total Time: 52112 miliseconds Average Time: 5211.0 miliseconds | ||||
|
投稿日時: 2006-11-19 13:59
すみません、ソースを[code]タグで囲むのを忘れてしまいました。。
| ||||
|
投稿日時: 2006-11-19 14:10
気になったのはStatement Test.の箇所でstmt.executeQuery()を
実行した後に結果の取得をしていませんが、ResultSetで結果を取得した 際もおなじようなパフォーマンスでしょうか? MySQLのJDBCドライバの実装がどうなっているかは知りませんが、 データを遅延ロードするようになっていたら正しく計測されませんよね。 とりあえず思いついただけのネタなのではずしているかもしれませんが。 # なんとなくインデントがずれていますね…。 | ||||
|
投稿日時: 2006-11-19 14:45
"PreparedStatementの実行時間がStatementの1/3程度になると期待"の根拠は
なんですか? JDBCドライバの実装に依存すると思いますが、 for文中でPreparedStatementを生成、破棄しても、 Statementより高速になるような実装なのか?と思います。 for文中で何度も生成せずに、for文の外でPreparedStatementを 一度だけ生成して、それを使いまわしたら、結果が変わるかも。 後は、nagiseさんと同意です。 | ||||
|
投稿日時: 2006-11-20 10:52
Statementクラスを使った結果が2回目以降格段によくなっているのは、おそらく
データキャッシュ、ステートメントキャッシュのどちらかあるいは両方が効いている からでしょうね。 興味深いのは、PreparedStatementの結果ですね。MySQLかJDBCドライバの実装に問題 がある可能性がありますが、どのような環境で実行したのでしょうか。 | ||||
|
投稿日時: 2006-11-20 13:09
問い合わせ毎にstmt,pstmtのクローズが必要ではないですか?
| ||||
|
投稿日時: 2006-11-20 17:56
とりあえず、PreparedStatementを使って速くなる要素とは、
1. パラメータを利用してPreparedStatementを使いまわす 2. JDBCドライバがSQLの解析結果のキャッシュに対応している 3. Batch Updateを利用して複数行の更新をまとめて行える といったところだと思うのですが。 少なくとも2と3はJDBCドライバ/DBの双方が対応している必要があります。 接続プールがPreparedStatementをキャッシュするケースもありますが、 Statementの置き換えとして使えば、多少なりともSQLの解析が入るので、 PreparedStatementの方が速くなる可能性は極めて低いでしょう。 この辺りをきちんとやらない限り、ベンチマークする意味なんてないのでは? きちんとやっても特定の状況や環境での計測結果に過ぎないです。 間違いだらけのベンチマークは害しか生まないですよ。 |
1