QueryDSL SQL 与 JDBCTemplate 之间的性能测试
Performance tests between QueryDSL SQL vs JDBCTemplate
我试图说服 "the higher ups" 使用 querydsl sql 来保持我们的持久性。但他们更喜欢 spring jdbctemplate,原因是它提供了最好的原始性能。
性能当然是我们的首要要求。这就是为什么 JPA 根本不是一个选项。 QueryDSL SQL 的开销是否太大而无法从我们的选项中剔除?
我想知道是否有任何 "recent" 性能测试来显示 querydsl sql 如何与 jdbctemplate 和 jpa 一起运行。
我遇到了 this。
我想知道 querydsl sql 与 jdbctemplate 和 jpa 实现相比的相对性能。
我做了一些性能测试来比较overhead/performancequerydsl和jdbctemplate的比较
这是我所做的
1. 创建了一个 spring 使用 querydsl 和 jdbctemplate
的引导项目
2. 创建了 2 个端点,1 个用于使用 querydsl,另一个用于 jdbctemplate。
3. querydsl 配置使用 spring 引导自动配置的数据源来配置其 SQLQueryFactory。
4. JdbcTemplate 也使用相同的自动配置数据源进行自动配置。
5.存储库中有2个类似查询的实现,一个使用querydsl,另一个使用jdbctemplate。查询相对复杂,由几个内部连接和 where 子句组成。
6. Service 方法有一个for 循环并在每次迭代中调用存储库方法。迭代次数可配置,已设置为 100,000 次迭代。
7. System.nanoTime() 在控制器中围绕服务方法使用,以计算执行存储库方法的多次迭代所花费的时间。
8. JdbcTemplate 执行 100,000 次存储库调用平均花费 800 毫秒。
9. Querydsl 执行 100,000 次存储库调用平均花费 5000 毫秒。
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 内存数据库。数据库只为每个 table 保存几条记录。以及 1 个与查询匹配的结果行。
该方法在 for 循环中执行(10 万次迭代)。并且在循环的 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);
}
分析您的应用程序并查看在查询中占用时间的内容。是查询的解析编译,还是查询本身?
您正在编写 return 整个域对象或列的子集(使用 JPA "select new BlaBlaDTO" 类型构造)的查询吗?
您是否考虑过使用 Spring Data JPA,您可以完全控制是要使用 RAW SQL、命名查询还是 Spring Data JPA 方法命名约定查询?
您的 JDBC 连接设置是否在数据库端缓存准备好的语句,以便它们只需要为具有不同参数的相同查询准备一次(这有很大的不同)?
您是否使用一级和二级缓存来提高服务器端性能?
选择原始 JDBC 作为首选机制最终会很糟糕;复杂查询、无脏检查、无乐观锁定等
Ammen.M 如果您正在寻找数据库访问方面的性能(在 JavaEE 平台中),最好的选择是纯 JDBC,但每个人都知道它的局限性和字符串的广泛使用原生 SQL。 Spring Data、JPA 或 QueryDSL,所有这些框架都为您提供了其他好处,例如类型安全、表和对象之间的关系映射。
因此,如果您的团队真的很关心性能,那应该是您的选择。
我试图说服 "the higher ups" 使用 querydsl sql 来保持我们的持久性。但他们更喜欢 spring jdbctemplate,原因是它提供了最好的原始性能。
性能当然是我们的首要要求。这就是为什么 JPA 根本不是一个选项。 QueryDSL SQL 的开销是否太大而无法从我们的选项中剔除?
我想知道是否有任何 "recent" 性能测试来显示 querydsl sql 如何与 jdbctemplate 和 jpa 一起运行。
我遇到了 this。 我想知道 querydsl sql 与 jdbctemplate 和 jpa 实现相比的相对性能。
我做了一些性能测试来比较overhead/performancequerydsl和jdbctemplate的比较
这是我所做的
1. 创建了一个 spring 使用 querydsl 和 jdbctemplate
的引导项目
2. 创建了 2 个端点,1 个用于使用 querydsl,另一个用于 jdbctemplate。
3. querydsl 配置使用 spring 引导自动配置的数据源来配置其 SQLQueryFactory。
4. JdbcTemplate 也使用相同的自动配置数据源进行自动配置。
5.存储库中有2个类似查询的实现,一个使用querydsl,另一个使用jdbctemplate。查询相对复杂,由几个内部连接和 where 子句组成。
6. Service 方法有一个for 循环并在每次迭代中调用存储库方法。迭代次数可配置,已设置为 100,000 次迭代。
7. System.nanoTime() 在控制器中围绕服务方法使用,以计算执行存储库方法的多次迭代所花费的时间。
8. JdbcTemplate 执行 100,000 次存储库调用平均花费 800 毫秒。
9. Querydsl 执行 100,000 次存储库调用平均花费 5000 毫秒。
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 内存数据库。数据库只为每个 table 保存几条记录。以及 1 个与查询匹配的结果行。
该方法在 for 循环中执行(10 万次迭代)。并且在循环的 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);
}
分析您的应用程序并查看在查询中占用时间的内容。是查询的解析编译,还是查询本身?
您正在编写 return 整个域对象或列的子集(使用 JPA "select new BlaBlaDTO" 类型构造)的查询吗?
您是否考虑过使用 Spring Data JPA,您可以完全控制是要使用 RAW SQL、命名查询还是 Spring Data JPA 方法命名约定查询?
您的 JDBC 连接设置是否在数据库端缓存准备好的语句,以便它们只需要为具有不同参数的相同查询准备一次(这有很大的不同)?
您是否使用一级和二级缓存来提高服务器端性能?
选择原始 JDBC 作为首选机制最终会很糟糕;复杂查询、无脏检查、无乐观锁定等
Ammen.M 如果您正在寻找数据库访问方面的性能(在 JavaEE 平台中),最好的选择是纯 JDBC,但每个人都知道它的局限性和字符串的广泛使用原生 SQL。 Spring Data、JPA 或 QueryDSL,所有这些框架都为您提供了其他好处,例如类型安全、表和对象之间的关系映射。
因此,如果您的团队真的很关心性能,那应该是您的选择。