继承EJB3应用程序的性能优化策略

时间:2010-09-29 07:40:13

标签: java performance jpa ejb-3.0

我被要求查看具有严重性能问题的遗留EJB3应用程序。原作者不再可用,所以我得到的只是关于不可接受的性能的源代码和一些用户评论。我的个人EJB3技能非常基础,我可以阅读并理解带注释的代码,但直到知道这一切。

服务器有一个数据库,几个EJB3 bean(JPA)和一些无状态bean,只是为了允许远程客户端的4..5域对象上的CRUD。客户端本身是一个Java应用程序。只有少数并行连接到服务器。从用户评论中我了解到了

  • 客户端/服务器应用在LAN中表现良好
  • 该应用在WAN(1MB或更多)上实际上无法使用,因为读取和更新操作花费的时间太长(最多几分钟)

我已经看到一个潜在的问题 - 在所有EJB上,所有关系都已使用提取策略FetchType.EAGER定义。这是否可以解释读取操作的性能问题,是否建议使用提取策略进行调优?

但这不能解释更新操作的性能问题,或者它会不会?更新由EntityManager处理,客户端只是将域对象传递给管理器bean,并且仅使用manager.persist(obj)进行持久化。也许发送到服务器的域对象太大(可能是EAGER策略的副作用)。

所以我的实际理论是在一个相当慢的网络上发送太多字节,我应该考虑减少结果集的大小。

根据您的经验,导致CRUD操作性能问题的典型和最常见的编码错误是什么?我应该从哪里开始调查/优化?

4 个答案:

答案 0 :(得分:4)

  

在所有EJB上,所有关系都已使用提取策略FetchType.EAGER定义。这会解释读操作的性能问题吗?

根据类之间的关系,您可能会获取比检索实体时实际需要的更多(整个数据库?)?

  

建议使用提取策略进行调整吗?

我不能说制造所有关系EAGER是一种非常标准的方法。根据我的经验,当您想要为给定的用例加载关联时,通常会让它们保持懒惰并使用“获取联接”(一种允许获取关联的联接类型)。

  

但这不能解释更新操作的性能问题,或者它会不会?

可以。我的意思是,如果应用程序在读取时检索大胖对象图,然后再发送相同的胖对象图以更新根实体,则可能会有性能损失。但是代码使用em.persist(Object)更新实体有点奇怪。

  

根据您的经验,导致CRUD操作性能问题的典型和最常见的编码错误是什么?我应该从哪里开始调查/优化?

显而易见的包括:

  1. 检索超出要求的数据
  2. N + 1请求问题(糟糕的提取策略)
  3. 写得不好的JPQL查询
  4. 非适当的继承策略
  5. 不必要的数据库命中(即缺少缓存)
  6. 我会在接触任何东西之前先编写一些集成测试或功能测试,以保证你不会改变功能行为。然后,我将激活SQL日志记录并开始查看主要用例的生成的SQL并处理以上几点。

答案 1 :(得分:1)

从DBA职位。

  

根据您的经验,导致CRUD操作性能问题的典型和最常见的编码错误是什么?我应该从哪里开始调查/优化?

  1. 关闭缓存
  2. 启用sql日志记录Ejb3 / Hibernate默认生成许多非常愚蠢的查询。
  3. 现在你明白我的意思了。
  4. 将FetchType.EAGER更改为FetchType.LAZY
  5. 对em.find em.persist
  6. 之间的大型业务逻辑说“不”
  7. 使用ehcache http://ehcache.org/
  8. 启用实体缓存
  9. 如果可以,请使主键不可变(@Column(updatable = false,...)
  10. 启用查询缓存
  11. 如果你想要大的性能,永远不要使用Hibernate: http://www.google.com/search?q=hibernate+sucks

答案 2 :(得分:1)

我的情况是类似的性能问题并不取决于获取策略。或者让我们说在现有的获取策略中改变业务逻辑是不可能的。在我的情况下,解决方案只是添加索引。 当您的JPA对象模型有很多关系(OneToOne,OneToMany,...)时,您通常会使用带有大量连接的JPQL语句。这可能导致复杂的SQL转换。当您查看数据模型(由JPA生成)时,您将发现任何表行都没有索引。 例如,如果您有一个Customer和一个具有oneToOne关系的Address对象,一切都会在第一眼看上去很好。客户和地址有一个外键。但是如果你做这样的选择

Select c from Customer as c where c.address.zip='8888'

你应该关注表ADDRESS中的表格列'zip'。在部署期间,JPA不会为您创建此类索引。所以在我的情况下,我只需添加索引就可以加快数据库性能。 数据库中的SQL语句如下所示:

 ALTER TABLE `mydatabase`.`ADDRESS` ADD INDEX `zip_index`(`IZIP`);

答案 3 :(得分:0)

在问题和其他答案中,我听到很多“可能”和“可能”的声音。

首先了解发生了什么。如果你还没有这样做,我们都只是在黑暗中戳。

我不是这类系统的专家,但this method适用于任何语言或操作系统。

当你发现它需要花费的时间太长时,为什么不在这里总结呢? 我特别想知道这是否是可能被猜到的东西。