|
锁定老贴子 主题:Hibernate的性能
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
|---|---|
| 作者 | 正文 |
|
最后更新时间:2004-07-10
我们的项目从去年12月份启动,采用了Struts+Hibernate的架构,一开始使用Hibernate的时候速度极快,对象操作异常方便,大家都说爽歪歪。
可惜好景不长,随着我们对象关系的不断复杂,数据量的不断增加,Hibernate的性能急剧下降。具体表现为:我们在设计对象时采用了很多的one-to-many和many-to-one的关系,在取某个对象的几个简单的属性时,它会把所有关联的子对象都取出来,经常出在取一个简单属性的时候,调试窗口的SQL语句一屏一屏地往下闪。到最后我的一个test跑完需要12分钟。 在忍无可忍之下,我们开始性能优化方案,以下我们优化所做的一些事情: 1、将所以one-to-many的关系里将lazy设成true 2、修改hibernate.properties,增加了以下两句: hibernate.jdbc.fetch_size=50 hibernate.jdbc.batch_size=100 3、调整WebLogic的pool 4、利用Hibernate提供的CGLIB Proxy机制,使many-to-one关系的子对象也可以lazy initialization (但是我发现调试窗口里仍会有取子对象的SQL语句,但速度确实快了)。 5、利用Hibernate提供的Cache机制,对关键对象使用Cache 结果优化以后,我的test可以从原来的12分钟变成50秒钟跑完。 原以为万事大吉了,但当我们面对客户的时候,才发现我们系统的性能还远远不够。 我们现在系统试运行约两个月,经常在数据保存或者查询时等上一分钟甚至两分钟。 由于客户原来的系统用asp+SQL Server写的,速度很快。二者一对比,我们就被客户骂得惨不忍睹。 优化真是一件很烦人的事,在不改动系统框架的情况下,不知还有哪些提高系统性能的方法?[/swf] 声明:JavaEye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
|
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
同感,虽然我不用,不懂hibernate.
前段时间,我们做了个项目,对一些取数的过程,采用了javascript脚本,再通过bsf编译,运行时,时间巨长,人家说以前用foxpro做的,快多了,弄得我们很没面子。 |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
我也用 Struts+Hibernate 做大型项目,在并发很高时,每天4500人次访问量的情况下,性能也相当不错.
做的时间有几点考虑: 1.大东东.如果很多很多的one-to-many和many-to-one的关系. 必定会影响性能,我刚学习Hibernate 时就有这种直觉,所以我们没有用one-to-many和many-to-one的关系.而是象SQL一样的去操作表的关系标识符. 2.如果超大的系统,最终必须生成HTML的文件.就是有数据库中有数据更新时,自动生成一个HTML文件.大多数用户是在只读状态.在只读状态下就只去显示HTML文件,节省很多资源. 3.更用CHACHE表技术,把访问量高的记录自动提到CACHE表中. |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
谢谢dhj1给我提的建议。
在hibernate网站上看到的好多资源几乎都说hibernate的性能不错,而且很多人开发的系统性能也不错,包括dhj1的,看来hibernate无罪,是我们设计得太滥了。 不过还是有点疑问。 1、dhj1提到的第一点很有道理。我们确实在有些关键的地方用了标识符来关联。但是我们这个系统的关联实现太多了,如果所以有东西都用标识符作关联的话,那我们的实体层设计就退化成为面向关系的ER图设计,那我们要Hibernate何用?我用感觉用Hibernate时最大的便利不是在写代码的时候用对象的操作代替SQL语句,而是在建模的时候可以用面向对象的思维把很复杂的逻辑用UML图表示出来,然后直接转化成实体。所以我们在性能影响太大的地方采用了面向对象和关系相结合的方式,但在更多的地方仍然只能采用对象关联的方式。 2、生成静态HTML,对特定的系统确实有用,但我们系统中的数据几乎都是动态的,所以实现起来有困难。而且我也不太清楚这样做的难度有多高,具体怎么实现,请dhj1指点迷津。 3、Cache我们已经采用了。但proxy的用法我至今仍然有点迷糊。 在Hibernate的文档里似乎只要在定义文件里加这么一句就可以了: <class name="eg.Order" proxy="eg.Order"> 但实际使用时我们发现这样做之后,Hibernate取数据时的SQL语句似乎一句都没有少。 我们现在的想法是自已来实现Proxy类,它的接口与实体完全一样,在Proxy里SQL语句来实现取数据操作。不知是否可行? |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
我在设计系统时,对每个对象图都会采用两套映射模型,
一套用于映射实际的UML,当然包括引用,这套对象图主要用于根据关联对象的属性来查询对象时使用,很少用于更新数据,除非是聚集类. 另一套映射,把对象引用映射为Long型的属性,传递到业务层或表示层,需要相关的对象引用时,再用这个引用来load对象.而且,对于需要load的对象可以使用代理或直接多映射一个简单类来处理. 另外,对于大数据量的查询或表的关联层次较深(超过三层),建议采用jdbc直接处理. |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
我们现在也正在用hibernate进行项目开发
我认为不是所有相关的表都要做one Many,many one映射的 比如说一个用户和他的定购业务,我们做了双向关联。 但是这个用户的话单就不能和用户做任何关联了。话单表每天都有数十万条,就是做manyone关联也非常吓人,宁可到时候用hql来查询 |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
呵呵,请教sanwa,这两套映射模型如何在一个应用中同时使用?
|
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
我用hibernate,是可以减少开发工作量. 特别在开发中或维护过程中对表结构的改动,用HIBERNATE是很方便的.
做了DAO后,对表的父子关系等的处理,通过ID标识,也只是两三句程序语句.操作也很方便,而且更灵活. 生成静态HTML,以后我做过这样的系统,并在XXX省信息港网站上大量使用,性能当然不错,同时1400人在线(真正的在线,不是那种用网页搞个几分钟刷新一次延时的那种在线),性能也不错,开发当然会有一些难度. 我说的CACHE不是说用HIBERNATE的CACHE.而是自已开发的,把访问量高的信息自动放到一个表中去,这个表保证只有100访问量最高的条记录.多于100条记录的就出去了. |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-10
举个例子,比如用户的权限,在我们的系统中涉及用户(User)、权限(Acl)、组件(Component)、组件类(componentDomain)等几个对象的关联。
第一套映射图,反映他们的实际关系,即对应UML模型。User和Acl的关联映射为idbag,不要直接映射为set,因为在我设计的关联表中存在代理主键,代理主键在第二套映射图中实际为用户权限的id. 第二套映射图,只映射用户(UserSO)和用户拥有的权限(UserAclSO),是one to many的关系。 后缀SO表示相关类的简单对象映射类。 这样,当客户端需要获取某个用户的所有权限时,直接用第二套映射图。返回的集合中就只包括Acl的id。如果要获取用户对某个组件域的权限,则用第一套映射图,用强大的HQL查询,再转换为第二套映射图返回到客户端。 当更新用户的权限时,也用第二套映射图,直接操作UserSO和UserAclSO,传回更新。 使用类似的设计策略时,对many to many的关联表,都采用代理主键,而不是联合主键,这样,两套映射图都较容易存取数据。只是,多数情况下用第二套映射图。 当然,我的程序架构是Swing + Session Bean + DAO + Hibernate + DB,Swing和Session Bean的通信可以用HTTP或RMI,在我的架构中,lazy loading发挥不了多大的作用,才采取这种策略。如果在lazy loading可以发挥作用的地方,对大多数对象图,是没有必要采取这种策略的。 另外,在我的架构中,swing层有一个组件是可以根据一个ID来加载这个类的属性,直接用jdbc实现的,独立于Hibernate |
|
| 返回顶楼 | |
|
最后更新时间:2004-07-11
我也说上一句吧。
虽然HB是好,方便,但有关数据库设计的一些性能原则还是要考虑的。 毕竟它只是Mapping而已。 所以也要设置索引等东西。 |
|
| 返回顶楼 | |









