QueryDSL SQL与JDBCTemplate之间的性能测试

问题描述 投票:8回答:3

我试图说服“更高层次”使用querydsl sql来保持持久性。但是他们更喜欢spring jdbctemplate,原因是它提供了最好的原始性能。

表现是我​​们对课程的首要要求。这就是为什么JPA根本不是一个选择。 QueryDSL SQL开销是否过多,无法从我们的选项中解脱出来?

我想知道是否有任何“最近的”性能测试来显示querydsl sql如何使用jdbctemplate和jpa。

我遇到了this。我想知道querydsl sql与jdbctemplate和jpa实现进行比较时的相对性能。

java spring jdbc querydsl
3个回答
14
投票

我做了一些性能测试来比较querydsl和jdbctemplate之间的开销/性能比较。

这就是我做的 1.创建了一个使用querydsl和jdbctemplate的spring boot项目 2.创建2个端点,1个用于使用querydsl,另一个用于jdbctemplate。 3. querydsl配置使用spring boot autoconfigured数据源来配置其SQLQueryFactory。 4. JdbcTemplate也使用相同的自动配置数据源进行自动配置。 5.存储库中有两个类似查询的实现,一个使用querydsl,另一个使用jdbctemplate。查询相对复杂,由几个内部联接和where子句组成。 6. Service方法有一个for循环,并在每次迭代中调用repository方法。迭代次数是可配置的,并且已设置为100,000次迭代。 7. System.nanoTime()用于控制器中的服务方法,以计算执行存储库方法的多次迭代所花费的时间。 8. JdbcTemplate平均花费800毫秒来执行100,000个存储库调用。 9. Querydsl平均花费5000毫秒来执行100,000个存储库调用。 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.使用连接执行相对复杂的查询。 2.从结果集中填充bean。

我正在使用H2内存数据库。数据库只保存每个表的几个记录。和1个匹配查询的结果行。

该方法在for循环中执行(1万亿次迭代)。并且在循环周围的System.nanoTime()的帮助下计算时间。

它是一个具有不同端点的spring引导项目(一个用于querydsl,另一个用于jdbctemplate)。 querydsl和queryfactory的配置如下

  @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
投票

分析您的应用,查看查询中花费的时间。它是查询的解析和编译,还是查询本身?

您是在编写返回整个域对象或列子集的查询(使用JPA“select new BlaBlaDTO”类型构造)吗?

您是否考虑过使用Spring Data JPA,您可以完全控制是否要使用RAW SQL,命名查询或Spring Data JPA方法命名约定查询?

您的JDBC连接是否设置为在数据库端缓存预准备语句,以便只需为具有不同参数的相同查询准备一次(这会产生巨大差异)?

您是否使用一级和二级缓存来提高服务器端性能?

选择原始JDBC作为首选机制将最终变得糟糕;复杂的查询,没有脏检查,没有乐观锁定等。


0
投票

Ammen.M如果你正在寻找数据库访问方面的性能(在JavaEE平台中),最好的选择是纯JDBC,但是每个人都知道它的局限性以及字符串与本机SQL的广泛使用。 Spring Data,JPA或QueryDSL,所有这些框架都为您提供了其他好处,如类型安全,表和对象之间的关系映射。

所以如果你的团队真的关心应该是你的赌注。

© www.soinside.com 2019 - 2024. All rights reserved.