2016-06-30 12 views
8

私は、 "上位の"データベースに永続性のためにquerydsl sqlを使用するように納得させようとしています。しかし、彼らはspring jdbctemplateを好んでいます。なぜなら、それが最良の生のパフォーマンスを与えるからです。QueryDSL SQLとJDBCTemplateの間のパフォーマンステスト

パフォーマンスは私たちの主な要件です。 JPAはオプションではありません。 QueryDSLのSQLオーバーヘッドは、オプションから取り除くには多すぎますか?

querydsl sqlがjdbctemplateとjpaでどのように運営されているかを示す「最近の」パフォーマンステストがあるかどうかを知りたかったのです。

私はthisに出くわしました。 jdbctemplateとjpa実装と比較したときのquerydsl sqlの相対的なパフォーマンスを知りたい。

+0

_ "アセンブラ(またはC)が最速です" _組み込みのインテリジェンスの恩恵を受けるユースケースがない限り、あなたはそれらをProDSに納得させません。したがって、いくつかの書き換えを行います.SQLのエラー、短い表記法、QueryDSLの最適化、結果としてのSQLなど、いくつかのことを見つけることができます。 –

+1

私は、それが生のパフォーマンスと開発者の親しみやすさ(保守性)との間のトレードオフになることを理解します。私が証明したいこと(または私が期待していること)は、QueryDSL SQLはJPA/ORMよりもかなり優れたパフォーマンスを提供し、JDBCTemplateに比べてわずかに優れていることです。私はそれについていくつかの事実/数字を探しています。その間、私は自分自身でいくつかのテストを試しています。 –

答えて

11

私はquerydslとjdbctemplateの間のオーバーヘッド/パフォーマンスの比較を比較するためにいくつかのパフォーマンステストを行いました。ここで

は私がjdbctemplateためquerydslとquerydslを使用するための1、
2.作成した2エンドポイントjdbctemplateと別のものを使用しています
1.作成した春のブートプロジェクトをやったことです。
3. querydsl構成では、スプリングブート自動構成データソースを使用してSQLQueryFactoryを構成します。
4. JdbcTemplateも同じ自動設定データソースで自動設定されます。
5.リポジトリにはsimilaryクエリの2つの実装があり、一方はquerydslを使用し、もう一方はjdbctemplateを使用します。このクエリは比較的複雑で、内部結合とwhere句の2つから構成されています。
6. Serviceメソッドにはforループがあり、各反復でリポジトリメソッドを呼び出します。反復回数は設定可能で、1回の反復回数に設定されています。
7. System.nanoTime()は、コントローラのサービスメソッドの周りで使用され、リポジトリメソッドの多数の反復を実行するのにかかった時間を計算します。
8. JdbcTemplateは、1つのlakhリポジトリ呼び出しを実行するために平均800msを要しました。
9. Querydslは1つのlakリポジトリ呼び出しを実行するために平均5000msを要しました。
10.観測:Querydslは、同じクエリに対してJdbcTemplateより6倍遅いです。オーバーヘッドはおそらくquerydslのクエリのシリアル化にあります。

QueryDSLリポジトリ実装

List<Customer> customers = new ArrayList<>(); 
Customer customerObj = null; 
List<Tuple> customerTuples =queryFactory.select(customer.firstName,customer.status,customer.customerId). 
           from(customer).innerJoin(customerChat).on(customer.customerId.eq(customerChat.senderId)). 
           innerJoin(customerChatDetail).on(customerChat.chatDetailId.eq(customerChatDetail.chatDetailId)). 
           where(customerChatDetail.isRead.eq(true).and(customer.status.eq(true))).fetch(); 

    for (Tuple row : customerTuples) { 
     customerObj = new Customer(); 
     customerObj.setFirstName(row.get(customer.firstName)); 
     customerObj.setStatus(row.get(customer.status)); 
     customerObj.setCustomerId(row.get(customer.customerId)); 
     customers.add(customerObj); 
    } 
return customers; 

JdbcTemplate実装

List<Customer> customers = this.jdbcTemplate.query(
      "select first_name,status,customer_id from customer inner join v_customer_chat on customer.customer_id=v_customer_chat.sender_id inner join v_customer_chat_detail on v_customer_chat.chat_detail_id = v_customer_chat_detail.chat_detail_id where v_customer_chat_detail.is_read = ? and customer.status = ?;",new Object[] {true, true}, 
      new RowMapper<Customer>() { 
       public Customer mapRow(ResultSet rs, int rowNum) throws SQLException { 
        Customer customer = new Customer(); 
        customer.setFirstName(rs.getString("first_name")); 
        customer.setStatus(rs.getBoolean("status")); 
        customer.setCustomerId(rs.getLong("customer_id")); 
        return customer; 
       } 
      }); 

は基本的に私は、1つのより多くのオーバーヘッドが発生異なるライブラリーと対策とまったく同じことをやろうとしています。
1.ジョインを使用して比較的複雑なクエリを実行します。
2.結果セットからBeanを移入します。

私はH2インメモリデータベースを使用しています。データベースには、各テーブルのレコードが2つしかありません。クエリに一致する結果行が1行あります。

このメソッドはforループ(1 lakh反復)で実行されます。そして、ループの周りのSystem.nanoTime()の助けを借りて計算された時間。

エンドポイントが異なる春のブートプロジェクト(querydsl用とjdbctemplate用)。

@Autowired 
public DataSource dataSource; 

@Bean 
public PlatformTransactionManager transactionManager() { 
    return new DataSourceTransactionManager(dataSource); 
} 

@Bean 
public com.querydsl.sql.Configuration querydslConfiguration() { 
    SQLTemplates templates = H2Templates.builder().build(); 
    com.querydsl.sql.Configuration configuration = new com.querydsl.sql.Configuration(templates); 

    configuration.setExceptionTranslator(new SpringExceptionTranslator()); 

    return configuration; 
} 

@Bean 
public SQLQueryFactory queryFactory() { 
    Provider<Connection> provider = new SpringConnectionProvider(dataSource); 
    return new SQLQueryFactory(querydslConfiguration(), provider); 
} 
1

アプリをプロフィールやクエリで時間がかかっているかを見る次のようにquerydslとqueryfactoryのための設定が行われます。それは、クエリの解析やコンパイル、またはクエリ自体ですか?

JPA「select new BlaBlaDTO」型構文を使用して、ドメインオブジェクト全体または列のサブセットを返すクエリを記述していますか?

RAW SQL、名前付きクエリ、またはSpring Data JPAメソッドの命名規則の問合せを使用するかどうかを完全に制御できるSpring Data JPAの使用を検討しましたか?

JDBC接続を準備してデータベース側にプリペアドステートメントをキャッシュするようにしました。これにより、異なるパラメータを持つ同じクエリに対して一度だけ準備する必要があります(これは大きな違いになります)。

第1および第2レベルのキャッシュを使用してサーバー側のパフォーマンスを向上させていますか?

raw JDBCを優先するメカニズムを選択すると、ひどいことになります。複雑なクエリ、汚れのないチェック、オプティミスティックロックなどなし

0

Ammen.Mデータベースアクセスの観点から(JavaEEプラットフォームで)最良のオプションは純粋なJDBCですが、誰もがその限界とネイティブSQLでの文字列の広範な使用。 Spring Data、JPA、QueryDSLなど、これらのフレームワークはすべて、型安全性、表とオブジェクト間のリレーショナル・マッピングなどの利点を提供します。

あなたのチームが本当にあなたの賭けであるべきパフォーマンスについて懸念している場合。

関連する問題