我有一个开源Java应用程序,它使用Hibernate和HSQLDB来实现持久性.在我的所有玩具测试中,事情都很快,一切都很好.我有一个客户连续几个月运行该软件,他们的数据库在那段时间内显着增长,并且性能逐渐下降.我终于想到数据库可能是问题所在.据我在日志语句中可以看出,服务器中的所有计算都很快发生,因此这与DB可能出错的假设是一致的.
我知道如何对程序进行正常的分析,以确定热点的位置以及占用大量时间的内容.但是我所知道的所有分析器都监视程序内的执行时间,并且不会给你任何有关外部资源调用的帮助.人们使用哪些工具来分析使用外部数据库调用的程序,以找出优化性能的位置?
一个小小的盲目搜索已经找到了一些热点 - 我注意到一个电话,我在列举特定类的所有对象,以便找出是否有任何.标准[.setMaxResults(1)]的一行更改将该调用从半秒更改为几乎瞬时.我还看到在单个事务中多次向db询问相同问题的地方.我还没有弄清楚如何缓存答案,但我真正想要的是一个工具来帮助我更系统地寻找这些事情.
我有一些代表不可变对象的类(数量,价格,概率).有没有办法告诉Hibernate对象永远不会改变,所以它可以重用对象,而不是为每个0或1或Price = $ 1的实例创建一个新对象?
我最终创建了这些类,因为我发现双打并不能很好地表示用户输入的数字.用户输入十进制数字,如果将它们转换为双精度数,则会立即失去精度(有时也会失去正确性).因此,我用这些基于BigDecimal的对象替换了所有数字(除了短期的int).
在之前的几个项目中,性能优化的一个重要步骤是缓存小数字,因此每次我们引用0或1或者特定项目中常见的任何其他小数字时,我们都不会创建新对象.所以我怀疑如果hibernate知道它可以重用特定类型的对象,那么它也可以节省大量资金.
作为一个干净的编程实践,它们是纯数字和不可变的,这意味着Java代码不必担心共享对象和副作用.我已经为我的代码中常用的数字定义了一些清单常量,但是Hibernate为它从数据库中分页的每个数字创建了一个新对象.(怎么会这样呢?它不知道它们是不可变的,所以它不能假设它们可以共享.)
此时我还将所有这些对象都转换为hibernate组件,因此我不必担心在数据库中查找和删除任何不再使用的数字.但这也意味着不再有Quantity.hbm.xml来放置注释,即使hibernate支持这样的注释.
顺便说一句,这次重写最令人反感的方面是所有的算术现在都显示为a.times(b), c.plus(d.minus(e)),等等.但这是一个正确性问题,所以我认为我没有选择.