【问题标题】:JPA/Hibernate 50% slower than using simple JDBCJPA/Hibernate 比使用简单 JDBC 慢 50%
【发布时间】:2015-01-09 09:51:22
【问题描述】:

首先我想说,我远不是 JPA 和 Hibernate 方面的专家。但是我遇到了一些我完全陷入困境的事情,因为我不了解事情在下面是如何工作的,也不知道如何调试它。

我有一个网络应用程序(Spring + JPA2.0)。我有一个算法,可以使用来自 PostrgeSQL 数据库的数据为用户计算分数。为了衡量算法的速度,我对 1 个用户进行了计算。

耗时 72 秒。 (我觉得这次有点奇怪,因为我知道它不应该花那么长时间)

所以我所做的就是用简单的 JDBC 连接 (conn = DriverManager.getConnection(url, props);)) 替换数据库调用 (entityManger.createQuery(...)),然后我在不使用 JPA 的情况下从数据库中提取数据。

计算同一用户的分数需要 35 秒...

使用 JPA 会使计算变慢 50% 是否正常?我的意思是我会认为是的,时间会比简单地使用 jdbc 多“一点”,而是 50% ??

是否有任何我不知道的配置可以解释这种差异?

这是算法的伪代码。 calculateScore 在循环内调用 2000 次:

public double calculateScore(userId, placeId) {

//This returns in average 5 columns
List<Object[]> datas = entityManager.createNativeQuery("SELECT info1, info2, info3 WHERE user_id=.. and place_id=...").getResultList();
..
..
for (Object[] result : datas) {
 info1 = result[0] // Integer
 info2 = result[1] // Integer
 info3 = result[2] // Double

 if (info3 == null) {
     info3 = calculateMissing(..)
 }

 .. calculation ..

 return result
}

private double calculateMissing(..) {

    //this query returns maximum 20 rows 
    List<Double> data =  entityManager.createNativeQuery("SELECT info FROM..."). getResultList;


    //So here we could have UP TO 20 call to the db
    while(some cond) {
       data2 =  entityManager.createNativeQuery("SELECT * FROM...).getOne()
       if (data2 ..)
         cond = false
      ..
      }

    ... calculation ..

   return result;
}

所以这是我对数据库的“三个”小选择。

编辑 1

我已经尝试缩小问题的“确切”位置。我已经一一替换了从 jdbc 到 JPA 的调用。似乎while循环是造成50%(几乎)时间损失的循环。从一开始就做 dis 是一个非常糟糕的主意,但我不知道 JPA 根本不会喜欢这个。

我已将 while 循环替换为更智能的 SQL 查询。现在算法在 15 秒而不是 70 秒内运行!

在 12 秒内,而不是 JDB 版本的 35 秒。

【问题讨论】:

  • JPA 肯定会引入开销,尤其是与反射相关的开销,但这种情况表明您的方法存在根本性的问题。
  • 我将编辑我的问题以包含有关选择类型、数据大小等的更多详细信息。
  • 我猜,您的查询检索到的数据远少于使用 JPA 时检索到的数据(可能是由于急切地获取某些集合等)。
  • 代码异味:从数据库中获取结果列表后,您正在对结果列表执行一些极端操作,而无需过滤(如果有),这些操作应该在数据库端(通过 JPA)执行。在循环内部执行一条 SQL 语句,先得到一个泛化列表,然后在前端对列表执行操作,这似乎不是一个好的做法。本质上,这些测试用例似乎不是健全的测试用例(虽然 ORM 基本上往往有点慢,但如果精确使用优化技术,那应该不会太多)。
  • 至少部分问题在于您不断地重新创建而不是重复使用查询,但这看起来像是您应该在 SQL 中执行的那种聚合操作并只返回结果。

标签: spring performance jpa slowdown


【解决方案1】:

在通过主键检索记录时,我发现 JPA/Hibernate 和 JDBC 之间存在很大差异。

如果是平面对象模型,差异可能会特别大。随着模型复杂度的增加,性能变得更加均匀。

另外,考虑到使用 JPA 意味着在应用程序启动时创建一个连接池(使用 JDBC 则不需要),因此使用 JPA 的第一个事务可能比使用 JDBC 花费更长的时间。

【讨论】:

    【解决方案2】:

    根据我的经验,hibernate/jdbc 之间的速度差异似乎对于小型查询很重要。另一方面,当您尝试使用大量结果时,性能非常相似。

    在实际使用中确实不错。小查询仍然运行足够快。长时间运行的查询(这应该是您的主要关注点)具有相似的性能。

    【讨论】:

      猜你喜欢
      • 2013-01-11
      • 2013-02-15
      • 2023-03-18
      • 2023-04-08
      • 1970-01-01
      • 2014-01-29
      • 2017-08-24
      • 2012-08-29
      • 2017-07-17
      相关资源
      最近更新 更多