我被要求查看具有严重性能问题的遗留EJB3应用程序。原作者不再可用,所以我得到的只是关于不可接受的性能的源代码和一些用户评论。我的个人EJB3技能非常基础,我可以阅读并理解带注释的代码,但直到知道这一切。
服务器有一个数据库,几个EJB3 bean(JPA)和一些无状态bean,只是为了允许远程客户端的4..5域对象上的CRUD。客户端本身是一个Java应用程序。只有少数并行连接到服务器。从用户评论中我了解到了
我已经看到一个潜在的问题 - 在所有EJB上,所有关系都已使用提取策略FetchType.EAGER
定义。这是否可以解释读取操作的性能问题,是否建议使用提取策略进行调优?
但这不能解释更新操作的性能问题,或者它会不会?更新由EntityManager
处理,客户端只是将域对象传递给管理器bean,并且仅使用manager.persist(obj)
进行持久化。也许发送到服务器的域对象太大(可能是EAGER策略的副作用)。
所以我的实际理论是在一个相当慢的网络上发送太多字节,我应该考虑减少结果集的大小。
根据您的经验,导致CRUD操作性能问题的典型和最常见的编码错误是什么?我应该从哪里开始调查/优化?
答案 0 :(得分:4)
在所有EJB上,所有关系都已使用提取策略FetchType.EAGER定义。这会解释读操作的性能问题吗?
根据类之间的关系,您可能会获取比检索实体时实际需要的更多(整个数据库?)?
建议使用提取策略进行调整吗?
我不能说制造所有关系EAGER是一种非常标准的方法。根据我的经验,当您想要为给定的用例加载关联时,通常会让它们保持懒惰并使用“获取联接”(一种允许获取关联的联接类型)。
但这不能解释更新操作的性能问题,或者它会不会?
可以。我的意思是,如果应用程序在读取时检索大胖对象图,然后再发送相同的胖对象图以更新根实体,则可能会有性能损失。但是代码使用em.persist(Object)
来更新实体有点奇怪。
根据您的经验,导致CRUD操作性能问题的典型和最常见的编码错误是什么?我应该从哪里开始调查/优化?
显而易见的包括:
我会在接触任何东西之前先编写一些集成测试或功能测试,以保证你不会改变功能行为。然后,我将激活SQL日志记录并开始查看主要用例的生成的SQL并处理以上几点。
答案 1 :(得分:1)
从DBA职位。
根据您的经验,导致CRUD操作性能问题的典型和最常见的编码错误是什么?我应该从哪里开始调查/优化?
如果你想要大的性能,永远不要使用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适用于任何语言或操作系统。
当你发现它需要花费的时间太长时,为什么不在这里总结呢? 我特别想知道这是否是可能被猜到的东西。