2016-05-26 40 views
1

Oracle 11gを使用しています。私は3つのテーブル(A,B,C)を私のデータベースに持っていますA <one-many> B <many-one> C 私は、最初にACに、その後Bに3つの挿入を実行するコードを持っています。このコードは何度も実行され(200000)、各テーブルに200000の挿入操作が行われます。Spring jdbcTemplateとPreparedStatement。パフォーマンスの差

私は挿入を行うには二つの方法があります:私はための実行時間を測定し

List<String> bulkLoadRegistrationSql = new ArrayList<String>(20); 

for (int i=1; i<= total; i++) { 

    // 1. Define sql parameters p1,p2,p,3p4,p5 

    // 2. Prepare sql using parameters from 1 
    String sql1String = ... 
    String sql2String = ... 
    String sql3String = ... 

    bulkLoadRegistrationSql.add(sql1String); 
    bulkLoadRegistrationSql.add(sql2String); 
    bulkLoadRegistrationSql.add(sql3String); 

    if (i % 20 == 0) { 
      jdbcTemplate.batchUpdate(bulkLoadRegistrationSql 
       .toArray(new String[bulkLoadRegistrationSql.size()])); 
      //Clear inserted batch 
      bulkLoadRegistrationSql = new ArrayList<String>(20);  
    } 

} 

  1. JDBCのPreparedStatement:

    DataSource ds = jdbcTemplate.getDataSource(); 
    
    try (Connection connection = ds.getConnection(); 
        PreparedStatement statement = connection.prepareStatement(sql1); 
        PreparedStatement statement2 = connection.prepareStatement(sql2); 
        PreparedStatement statement3 = connection.prepareStatement(sql3);) { 
    
        connection.setAutoCommit(false); 
        final int batchSize = 20; 
        int count = 0; 
    
        for (int i=1; i<= total; i++) { 
    
         // Define sql parameters 
    
         statement.setString(1, p1); 
    
         statement2.setString(1, p2); 
         statement2.setString(2, p3); 
    
         statement3.setInt(1, p4); 
         statement3.setString(2, p5); 
    
         statement.addBatch(); 
         statement2.addBatch(); 
         statement3.addBatch(); 
    
         if (++count % batchSize == 0) { 
            statement.executeBatch(); 
            statement.clearBatch(); 
            statement2.executeBatch(); 
            statement2.clearBatch(); 
            statement3.executeBatch(); 
            statement3.clearBatch(); 
            connection.commit(); 
            System.out.println(i); 
         } 
         } 
    
         statement.executeBatch(); 
         statement.clearBatch(); 
         statement2.executeBatch(); 
         statement2.clearBatch(); 
         statement3.executeBatch(); 
         statement3.clearBatch(); 
         connection.commit(); 
        } 
        catch (SQLException e) { 
         e.printStackTrace(); 
        } 
    } 
    
  2. 春jdbcTemplateをと結果は私にとって非常に混乱しています。 スプリングjdbcTemplate

    200秒で1480秒、 JDBC PreparedStatementで実行される私はそれがPreparedStatement未満で効率的であるべきである、下にStatementを使用すること、jdbcTemplate源に見て、発見しました。しかし、結果の差は大きすぎるので、StatementPreparedStatementの違いのためにこれが起こるかどうかはわかりません。それについてのあなたのアイデアは何ですか? jdbcTemplatenamedParameterJdbcTemplateに置き換えられた場合、結果は理論的に等しくなるべきですか?

答えて

1

はい、それは、大部分の時間がデータベースからの応答を待つのに費やされたと仮定すると、はるかに近くなるはずです。 Springには独自のオーバーヘッドがあるため、クライアント側でさらにリソースを消費します。

プレースホルダを使用したプリペアド・ステートメントでは、OracleはSQLを1回のみ解析し、プランを1回生成します。次に、解析結果とSQLの計画をキャッシュします。 JDBCTemplateの例では、各SQL文はパーサと異なって見えるため、サーバによって完全な解析とプラン生成が必要になります。 Oracleサーバーの馬力によっては、各SQL文の応答時間が長くなります。 200,000のSQLステートメントの場合、1280秒の正味の増加は、1コールにつき6.4ミリ秒追加されます。それは私には、追加の解析が必要なために合理的な増加のように思えます。

データベースの呼び出しにいくつかのタイミング情報を追加することをお勧めします。これにより、SQL応答時間が改善されたバージョンでより低いことを確認できます。

0

任意のSQLでは、アクセス・パスを計算するのに、データベース・エンジンの時間の50〜80%が費やされます。

PreparedStatementを直接使用すると、データベースエンジンはアクセスパスを1回計算し、(prepareフェーズでは)すでに計算されたアクセスパスへのハンドルを返します。プリペアド・ステートメントが呼び出されると、データベース・エンジンは、すでに用意されているアクセス・パスにパラメーターを適用し、カーソルを戻すだけで済みます。

0

Spring JDBCTemplateにはprepared prepared文を使用するメソッドもあります。これを参照してくださいlinkテスト結果は意味があります。準備された文と通常のSQLを使って実行を比較することはできません。

SpringのJDBCTemplateに、Preparedステートメント(例:以下の関数)を使用するオーバーロードされたbatchUpdateメソッドがあります。

INT []は[] batchUpdateメ(文字列のSQL、最終的なコレクションbatchArgs、最終 INT BATCHSIZE、最終ParameterizedPreparedStatementSetterのPSS)

関連する問題