论坛首页 Java企业应用论坛

为何每次问到传统sql如何调优就没人回答?另附几则hibernate性能优化实践

浏览 58531 次
该帖已经被评为良好帖
作者 正文
   发表时间:2010-03-22  
大多数反对使用hibernate的同志,张口必说hibernate有性能问题,不好调优,对DBA不友好。可从来没有任何一个人具体指出hibernate哪里有性能问题,为什么不能调优,哪方面对DBA不友好。

大家去面试过,有些同志也有面试别人的经验,应该明白一点:务虚很容易。什么性能啦,什么并发啦,什么管理啦。每个人张口都可以说出很多来,但是一旦开始玩真格的,那些没有实际经验的就会原型毕露了。不是我心眼坏,戴着有色眼镜去看人,而是社会复杂,害人之心不可有,防人之心不可无。精准的批评是一种鞭策,有则改之无则加勉。关键在于是否存在“三人成虎”的情况呢?

让咱们化繁为简吧,只问一句话:“阁下认为hibernate有性能问题,sql无法调优。”这个想法是切身体会呢?还是以讹传讹而来呢?如果是切身体会,那么恳请阁下受累一下,劳烦您把出现的问题稍微详细的描述一下,如果有可能的话,最好还能和大家稍微讨论一下这个问题出现的原因,以及解决方法。

下面算是我在实际项目中遇到的一些性能出现问题的场景,以及解决的方法,想必大家用过hibernate都应该耳闻能熟了,但是为了避免自己出现上面所说的“空口无凭”,还是斗胆拿出来献丑了。

1.N+1
  场景描述:产品product和产品分类product_category两张表,多对一关系。查询产品列表时,可能出现N+1问题。
  解决方法:
   1:使用fetch抓取,select p from Product p join fetch p.category c
   2:使用map直接搜索需要的列,select new Map(p.id as id, p.name as name, p.category.name as categoryName) from Product p

2.1:1无法lazy
  场景描述:申请表头和三张申请子表是一对一关系,其中子表对主表的关联可以实现延迟加载,主表无法延迟加载3个子表。造成每次读取主表以后,都同时发送三个sql查询三个子表的信息。
  解决方法:一对一关系的一方无法延迟加载是hibernate本身的bug,虽然可以使用instrument解决,但是要对字节码进行静态加强,不如直接改成多对一关联。

3.大批量插入数据
  场景描述:导入数据过多时,一级缓存会迅速膨胀,有时导致内存溢出。
  解决方法:我们用的方法是每隔一定数目(200条)就执行session.flush()和session.clear(),现在看来还是应该是用jdbc批量插入,或者应该直接导入到数据库里。

回过头来看一下,平常遇到的问题,基本都是因为N+1以及延迟加载使用的太随意造成的,我们对二级缓存的使用也不多,只是把一些常用的数据字典一次性缓存到内存里了。剩下的批量插入,批量更新,确实不应该依靠hibernate来解决,这时候幸好我们还有其他选择,使用hibernate也可以满足我们80%以上的需求。

下面就期待同仁提出实例反证了,向大家多多学习。
   发表时间:2010-03-22  
嗯,Hibernate不是万能的,JAVA无论哪种框架都不能100%有提供各种需求的完美解决方案.
  主要现在的公司很多喜欢装,才爱说这种话.
  说句简单的,也是我这几天的工作心得. 1+1=2大家都知道,当1+1什么时候能等于3?
同样还是1+1放在了不同的环境中就不一定那么容易解决了.具体需求也是一样的,所以才说需求分析很重要.就是要规避这种在常理下成立的而在真实开发中要规避的问题.不要说某些框架的好坏,你能解决问题,只是因为你身边能帮你的东西太多了,被你利用上了而已.当你不能解决的,更没理由去说.因为只是这问题对我们现在比较难而已.
  最后,还是希望各位有真正实用经验的Hibernate高手开发一些有用的资料.比如具体功能具体如何使用,会发现什么问题.这样JAVA框架才能真正开源,不然这种乱七八糟的开源,真的太恶心了.
0 请登录后投票
   发表时间:2010-03-22  
因为大家都认为
hibernate是个ORM框架
但是它不是.
1 请登录后投票
   发表时间:2010-03-22   最后修改:2010-03-22
我遇到过的 针对mysql 优化sql
use index语句hql不支持 需要自己扩展

为了性能 有些复杂的写法 只能使用原生sql

二级缓存可以满足一般需求 但对于查询缓存没找到很好的扩展机制 很多时候为了性能 查询缓存要自己做
0 请登录后投票
   发表时间:2010-03-22  
我来说一下我用的一些比较好的实践
1. 禁止多对多关系,改用一对多的关系。
2. 使用HQL语句进行查询
3. 把hibernate当做一个高级的SQL封装来用。
0 请登录后投票
   发表时间:2010-03-22  
还在考虑Hibernate性能啊!
现在都考虑直接走磁盘了。这样可以去掉日志,锁,认证, 索引文件可以大大的减少。
0 请登录后投票
   发表时间:2010-03-22  
妈妈的,最近两个面试,都是问道搞并发,海量数据的处理!
数据库的调优,

搞灾了............
0 请登录后投票
   发表时间:2010-03-22  
坦白说,碰到复杂或者多表联合查询,我都先写原生sql,然后再用hql实现同样的sql。性能问题没怎么碰到。
0 请登录后投票
   发表时间:2010-03-22  
对于大表的N+1问题 我们在设计数据库的时候为什么不适当的冗余呢?

产品表完全可以冗余产品分类

解决办法后很多
0 请登录后投票
   发表时间:2010-03-22  
有的人只能hibernate当 返回对象的工具用了 所以当然以为hibernate这不行那不行了 和他们着什么急呢
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics