【问题标题】:Performance OpenJPA query (3000+ records) is slow性能 OpenJPA 查询(3000+ 条记录)很慢
【发布时间】:2012-09-17 16:59:53
【问题描述】:

我正在使用带有内置 OpenJPA 1.2.3 和 Oracle 数据库的 Websphere Application Server 7。我有以下实体:

    @NamedNativeQuery(name=Contract.GIVE_ALL_CONTRACTS, 
        query="SELECT number, name \n" +
          "FROM contracts \n" +
          "WHERE startdate <= ?1 \n" +
          "AND enddate > ?1",
          resultSetMapping = Contract.GIVE_ALL_CONTRACTS_MAPPING)
    @SqlResultSetMapping(name = Contract.GIVE_ALL_CONTRACTS_MAPPING, 
        entities = { @EntityResult(entityClass = Contract.class, fields = {
          @FieldResult(name = "number", column = "number"),
          @FieldResult(name = "name", column = "name")
        })
    })
    @Entity
    public class Contract {
      public static final String GIVE_ALL_CONTRACTS = "Contract.giveAllContracts";
      public static final String GIVE_ALL_CONTRACTS_MAPPING = "Contract.giveAllContractsMapping";

      @Id
      private Integer number;
      private String name;

      public Integer getNumber() {
        return number;
      }
      public String getName() {
        return name;
      }
    }

以下代码用于检索合同:

Query query = entityManager.createNamedQuery(Contract.GIVE_ALL_CONTRACTS);
query.setParameter(1, referenceDate);

List contracts = query.getResultList();
entityManager.clear();

return contracts;

检索到的合同被传递给网络服务。

对于 3608 条记录,在 Oracle 开发人员中执行此查询大约需要 0.35 秒。 对 query.getResultList() 的调用大约需要 4 秒。

在实体的构造函数中使用记录器,它记录大约有 10-20 个使用相同时间戳创建的实体。然后 0,015 秒它做了别的事情。我猜是 OpenJPA 的东西。

有没有办法加快 OpenJPA?或者是唯一的解决方案缓存?

【问题讨论】:

  • 我建议你使用 profiler。

标签: java websphere openjpa


【解决方案1】:

对象创建可能在性能损失中占有相当大的份额。在服务器中运行代码时,您不仅要查询数据库,还要分配内存并为每一行创建一个新的 Contract 对象。扩展堆或垃圾回收周期可能会计入您观察到的空闲期。

我建议您浏览一下有关如何处理 large results sets 的 OpenJPA 文档。

【讨论】:

  • openjpa.FetchBatchSize 非常重要。在 Oracle 中(过去是?)只有 10 个。
  • 我添加了以下代码:OpenJPAQuery kq = OpenJPAPersistence.cast(query); JDBCFetchPlan fetch = (JDBCFetchPlan) kq.getFetchPlan(); fetch.setFetchBatchSize(100); fetch.setResultSetType(ResultSetType.SCROLL_INSENSITIVE); fetch.setFetchDirection(FetchDirection.FORWARD); fetch.setLRSSizeAlgorithm(LRSSizeAlgorithm.LAST); 当我调用网络服务时,它会在 +/- 600 毫秒内返回结果。这速度真快!感谢这个伟大的提示
  • 您也可以使用:query.setHint("openjpa.FetchPlan.FetchBatchSize", "100"); query.setHint("openjpa.FetchPlan.ResultSetType", "SCROLL_INSENSITIVE"); query.setHint("openjpa.FetchPlan.LRSSizeAlgorithm", "LAST");
【解决方案2】:

我建议您下载 VisualVM 并为所涉及的软件包设置分析。 VisualVM 可以显示在不同方法中花费的时间,理论上在您的情况下总计为 0.35 秒。您将能够分析代码、OpenJPA 和网络 IO 之间的总时间分布。这将帮助您识别瓶颈。

【讨论】:

  • @Natan Cox Network 可以完美地看到,只需将 java.io.* 包含在配置文件中即可。数据库通信将被视为 io.read 之类的东西,我不记得确切的方法名称。
猜你喜欢
  • 2018-09-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多