TL;DR相同的SQL查询,当在休眠状态下执行时,需要70秒以上,当使用sql developer执行时,只需1.5秒
我发现,当一个特定的查询由hibernate执行时,它所花费的时间要比我在sql客户端中运行生成的sql要长得多。例如,在启用休眠静态后,我可以在日志中看到
- 执行2条JDBC语句花费67839913762纳秒 *;相当于1.13分钟
但是,如果我使用生成的SQL并运行它,它最多只需要1.5秒。
谁能告诉我造成这种差异的可能原因是什么?我的理解是,执行JDBC语句的时间完全取决于DB,对吗?如果SQL是相同的,为什么它在休眠时执行得这么慢?
单一实体类
@Entity
@Data
@AllArgsConstructor
@Builder
public class GpCustomer {
@Id
@Column(name = "CUSTNO")
private String custno;
@Column(name = "COMPANY")
private String company;
}
示例库
@Repository
public interface GpCustomerRepository extends JpaRepository<GpCustomer, String> {}
示例服务
public Page<GpCustomer> findAllCustomers() {
Pageable limit = PageRequest.of(0,10);
return GpCustomerRepository.findAll(limit);
}
更新:hibernate统计数据
Session Metrics {
137214920 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
18734658 nanoseconds spent preparing 2 JDBC statements;
67839913762 nanoseconds spent executing 2 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
0 nanoseconds spent executing 0 flushes (flushing a total of 0 entities and 0 collections);
16386 nanoseconds spent executing 2 partial-flushes (flushing a total of 0 entities and 0 collections)
}
1条答案
按热度按时间f1tvaqid1#
这种行为的一个可能原因是Hibernate实际上获取所有数据,而SQL客户端可能只获取几行。像Hibernate那样实现所有行显然需要更长的时间。
另一个可能的原因是,优化器对待SQL客户端最有可能执行的“文学SQL”的方式不同,并且比Hibernate使用的参数化版本执行得更好。Hibernate使用带参数标记的
PreparedStatement
,因此这样的语句更加通用,优化器在规划查询时可能会对其估计感到悲观。一个“识字的SQL”,即没有参数标记就没有这个问题。优化器将为该SQL创建一个专门的查询计划。为了做一个公平的比较并排除这些缺陷,编写一个JDBC程序,使用
PreparedStatement
和参数标记来读取所有数据,即通过ResultSet
到达终点。然后您可以比较运行时。如果您受到第二个选项的影响,请与您的DB管理员讨论此问题。我知道Oracle在优化过程中有一些选项可以查看参数值,所以这可能会有所帮助。