??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲一区国产视频,国产理论电影在线观看,国产网站在线播放http://www.aygfsteel.com/zstop/category/48870.htmlzh-cnSat, 18 Jun 2011 21:41:06 GMTSat, 18 Jun 2011 21:41:06 GMT60[转]hibernate抓取{略http://www.aygfsteel.com/zstop/archive/2011/06/18/352584.html......Sat, 18 Jun 2011 07:33:00 GMThttp://www.aygfsteel.com/zstop/archive/2011/06/18/352584.htmlhttp://www.aygfsteel.com/zstop/comments/352584.htmlhttp://www.aygfsteel.com/zstop/archive/2011/06/18/352584.html#Feedback0http://www.aygfsteel.com/zstop/comments/commentRss/352584.htmlhttp://www.aygfsteel.com/zstop/services/trackbacks/352584.html原文Q?a >http://jiangxuwen7515.blog.163.com/blog/static/817523502010730481252/?fromdm&fromSearch&isFromSearchEngine=yes

一?/span>
hibernate抓取{略Q单端代理的扚w抓取fetch=select(默认Q?/span>/joinQ?/span>

试用例Q?/span>

Student student = (Student)session.get(Student.class, 1);
System.out.println(student.getName());
System.out.println(student.getClasses().getName());

1Q保?/span>默认Q同fetch="select",如:
<many-to-one name="classes" column="classesid"
fetch="select"/>

fetch="select",另外发送一?/span>select语句抓取当前对象兌实体或集?/span>

执行l果Q?/span>2条语?/span>

Hibernate: select student0_.id as id1_0_, student0_.name as name1_0_, student0_.class_id as class3_1_0_ from student_join student0_ where student0_.id=?
学生1
Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_
from classes_join classes0_ where classes0_.id=?
高一(1)?/span>

======================================

2Q设|?/span>fetch="join",如:
<many-to-one name="classes" column="classesid" fetch="join"/>

fetch="join",hibernate会通过select语句使用外连接来加蝲其关联实体或集合

此时lazy会失?/span>

执行l果Q一?/span>join语句

Hibernate: select student0_.id as id1_1_, student0_.name as name1_1_, student0_.class_id as class3_1_1_, classes1_.id as id0_0_, classes1_.name as name0_0_ from student_join student0_ left outer join classes_join classes1_ on student0_.class_id=classes1_.id where student0_.id=?
学生1
高一(1)?/span>

======================================================

二?/span>hibernate抓取{略Q集合代理的扚w抓取Q?/span>fetch=selectQ默认)/join/subselectQ?/span>

试用例Q?/span>

Classes c = (Classes) session.load(Classes.class, new Integer(1));
    System.out.println("Class.name=" + c.getName());
    Set stuSet = c.getStudents();
    System.out.println(stuSet.size());
    if(stuSet != null && !stuSet.isEmpty()){
     for(Iterator it = stuSet.iterator(); it.hasNext();){
      Student s = (Student) it.next();
      System.out.println("student.name=" + s.getName());
     }
    }

1Q保持默认,?/span>fetch="select",如:
<set name="students" inverse="true"
fetch="select">

fetch="select",另外发送一?/span>select语句抓取当前对象兌实体或集?/span>

试l果Q?/span>2条独立的查询语句

Hibernate: select classes0_.id as id0_0_, classes0_.name as name0_0_ from classes_join classes0_ where classes0_.id=?
Class.name=高一(1)?/span>
Hibernate: select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_
from student_join students0_ where students0_.class_id=?
9
student.name=
学生7
student.name=
学生3
student.name=
学生1
student.name=
学生8
student.name=
学生2
student.name=
学生4
student.name=
学生5
student.name=
学生9
student.name=
学生6

(2)fetch="join",如:
<set name="students" inverse="true"
fetch="join">

fetch="join",hibernate会通过select语句使用外连接来加蝲其关联实体或集合

此时lazy会失?/span>

试l果Q?/span>1条独立的join查询语句

Hibernate: select classes0_.id as id0_1_, classes0_.name as name0_1_, students1_.class_id as class3_3_, students1_.id as id3_, students1_.id as id1_0_, students1_.name as name1_0_, students1_.class_id as class3_1_0_ from classes_join classes0_ left outer join student_join students1_ on classes0_.id=students1_.class_id where classes0_.id=?
Class.name=
高一(1)?/span>
9
student.name=
学生6
student.name=
学生4
student.name=
学生9
student.name=
学生7
student.name=
学生2
student.name=
学生3
student.name=
学生8
student.name=
学生1
student.name=
学生5

(3)fetch="subselect",如:用在查询语句?/span>
<set name="students" inverse="true"
fetch="subselect">

fetch="subselect",另外发送一?/span>select语句抓取在前面查询到的所有实体对象的兌集合

试用例Q?/span>

List classList = session.createQuery("from Classes where id in (1,2,3)").list();
    for(Iterator iter = classList.iterator(); iter.hasNext();){
     Classes c = (Classes)iter.next();
     System.out.println("Class.name=" + c.getName());
     Set stuSet = c.getStudents();
     System.out.println(stuSet.size());
     if(stuSet != null && !stuSet.isEmpty()){
      for(Iterator it = stuSet.iterator(); it.hasNext();){
       Student s = (Student) it.next();
       System.out.println("student.name=" + s.getName());
      }
     }
    }   

当不?/span>fetch="subselect" ,卻I<set name="students" inverse="true">,l果如下Q?/span>

执行?/span>3条查询语?/span>

Hibernate: select classes0_.id as id0_, classes0_.name as name0_ from classes_join classes0_ where classes0_.id in (1 , 2 , 3)
Class.name=
高一(1)?/span>
Hibernate:
select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id=?
9
student.name=
学生8
student.name=
学生5
student.name=
学生3
student.name=
学生9
student.name=
学生7
student.name=
学生1
student.name=
学生4
student.name=
学生6
student.name=
学生2
Class.name=
高一(2)?/span>
Hibernate:
select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id=?
4
student.name=
学生3
student.name=
学生4
student.name=
学生1
student.name=
学生2
Class.name=
高一(3)?/span>
Hibernate:
select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id=?
0

当不?/span>fetch="subselect" ,卻I<set name="students" inverse="true" fetch="subselect">,l果如下Q?/span>

执行?/span>1条查询语句(嵌套子查询)

Hibernate: select classes0_.id as id0_, classes0_.name as name0_ from classes_join classes0_ where classes0_.id in (1 , 2 , 3)
Class.name=
高一(1)?/span>
Hibernate:
select students0_.class_id as class3_1_, students0_.id as id1_, students0_.id as id1_0_, students0_.name as name1_0_, students0_.class_id as class3_1_0_ from student_join students0_ where students0_.class_id in (select classes0_.id from classes_join classes0_ where classes0_.id in (1 , 2 , 3))
9
student.name=
学生8
student.name=
学生4
student.name=
学生5
student.name=
学生9
student.name=
学生6
student.name=
学生2
student.name=
学生3
student.name=
学生1
student.name=
学生7
Class.name=
高一(2)?/span>
4
student.name=
学生3
student.name=
学生4
student.name=
学生2
student.name=
学生1
Class.name=
高一(3)?/span>
0



... 2011-06-18 15:33 发表评论
]]>
[转]Hibernate性能优化要点http://www.aygfsteel.com/zstop/archive/2011/06/18/352571.html......Sat, 18 Jun 2011 04:27:00 GMThttp://www.aygfsteel.com/zstop/archive/2011/06/18/352571.htmlhttp://www.aygfsteel.com/zstop/comments/352571.htmlhttp://www.aygfsteel.com/zstop/archive/2011/06/18/352571.html#Feedback0http://www.aygfsteel.com/zstop/comments/commentRss/352571.htmlhttp://www.aygfsteel.com/zstop/services/trackbacks/352571.htmlRobbinȝ的Hibernate性能优化要点Q?/span>

1.量使用many-to-oneQ避免用单one-to-many
2.灉|使用单向one-to-many
3.不用一对一Q用多对一代替一对一
4.配置对象~存Q不使用集合~存
5.一对多使用Bag 多对一使用Set
6.l承使用昄多?nbsp; HQL:from object  polymorphism="exlicit" 避免查处所有对?br />7.消除大表Q用二U缓?br />    对于上面q些QRobbinq行了详l的讲解?br />one-to-manyQ?/strong>
     使用inverse=false(default)Q对象的兌关系是由parent对象来维护的
     而inverse=true的情况下Q一般用户双向多对多兌Q由子对象维护关联关p,增加子对象的时候需要显C:child.setParent(child)
     Z提高性能Q应该尽量用双向one-to-many inverse=trueQ在MVCl构中的DAO接口中应该直接用Session持久化对象,避免通过兌关系Q这句话有点不理解)Q而在单项关系中正用二U缓存,则可以大q提高以查询Z的应用?br />     多对一性能问题比较,但是要避免经典N+1问题?br />     通过主键q行兌Q相当于大表拆分表。(q个是区分面向对象设计和面向q程设计的一个关键点Q?br />list、bag、set的正运?/strong>
     one-to-manyQ?br />     A、用list 需要维护Index Column字段Q不能被用于双向兌Q而且必须使用inverse=falseQ需要}慎用在某些E有场合(基本上是不予考虑使用Q?br />     B、bag/set在one-to-many中语义基本相同,推荐使用bag
     many-to-oneQ?br />     A、bag和set不同Qbag允许重复插入Q徏议用set
在庞大的集合分页中应该用session.createFilter
    session.createFilter(parent.getChildren(),""),setFirstResult(0),setMaxResult(10))
避免N+1 参考(http://www.iteye.com/post/266972Q?/strong>
    在多对一的情况下Q查询child对象Q当在页面上昄每个子类的父cd象的时候会DN+1ơ查询,需要采用下面的Ҏ避免Qmany-to-one fetch="join|select"Q该Ҏ可能有问题)
inverse=true 无法l护集合~存Q还不是很理解集合缓存和对象~存Q?/strong>
OLTPcd的web应用Q可以群集水qx展,不可避免的出现数据库瓉
    框架能降低访问数据库的压力,采用~存是衡量一个框架是否优U的重要标准,从缓存方面看Hibernate
    A、对象缓存,l颗_度Q是针对表的U别Q透明化访问,因ؓ有不改变代码的好处,所以是ORM提高性能的法?br />    B、Hibernate是目前ORM框架中缓存性能最好的框架
    C、查询缓?br />最后Robbinq针对大家经常出现的Hibernate vs iBatis的讨行了一个ȝQ?br />   对于OLTP应用Q用ORM框架 而OLEB应用Q不定是什么应用)最好采用JDBC或者其他方法处?br />   Hibernate們֐于细颗粒度设计,面向对象Q将大表拆分为多个小表,消除冗余字段Q通过二~存提升性能?br />   iBatis們֐于粗颗粒度设计,面向关系Q尽量把表合qӞ通过Column冗余Q消除关联关p,但是iBatis没有有效的缓存手Dc?/span>

   可以说Robbin的性能ȝ对于使用Hibernate的开发h员有着很重要的Ҏ作用。非常感谢他无私奉献自己的经验?/span>



... 2011-06-18 12:27 发表评论
]]>
[转]加速你的Hibernate引擎Q下Q?/title><link>http://www.aygfsteel.com/zstop/archive/2011/06/18/352568.html</link><dc:creator>...</dc:creator><author>...</author><pubDate>Sat, 18 Jun 2011 04:03:00 GMT</pubDate><guid>http://www.aygfsteel.com/zstop/archive/2011/06/18/352568.html</guid><wfw:comment>http://www.aygfsteel.com/zstop/comments/352568.html</wfw:comment><comments>http://www.aygfsteel.com/zstop/archive/2011/06/18/352568.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zstop/comments/commentRss/352568.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zstop/services/trackbacks/352568.html</trackback:ping><description><![CDATA[原文: <a >http://www.infoq.com/cn/articles/hibernate_tuning-ii</a><br /><br /> <h3>4.6 HQL调优</h3> <h4>4.6.1 索引调优</h4> <p>HQL看v来和SQL很相伹{从HQL的WHERE子句中通常可以猜到相应的SQL WHERE子句。WHERE子句中的字段军_了数据库选择的烦引?/p> <p>大多数Hibernate开发者所常犯的一个错误是无论何时Q当需要新WHERE子句的时候都会创Z个新的烦引。因为烦引会带来额外的数据更新开销Q所以应该争取创建少量烦引来覆盖可能多的查询?br /><strong>4.1?/strong>让你使用一个集合来处理所有可能的数据搜烦条g。如果这不太实际Q那么你可以使用后端剖析工具来创Z个针对应用程序涉及的所有SQL的集合。基于那些搜索条件的分类Q你最l会得到一个小的烦引集。与此同Ӟq可以尝试向WHERE子句中添加额外的谓语来匹配其他WHERE子句?/p> <blockquote> <p><strong>范例7</strong></p> <p>有两个UI搜烦器和一个后端守护进E搜索器来搜索名为iso_deals的表。第一个UI搜烦器在unexpectedFlag、dealStatus、tradeDate和isold属性上有谓语?/p> <p>W二个UI搜烦器基于用户键入的qo器,其中包括的内定wtradeDate和isold以外q有其他属性。开始时所有这些过滤器属性都是可选的?br />后端搜烦器基于isold、participantCode和transactionType属性?br />l过q一步业务分析,发现W二个UI搜烦器实际是Z一些隐式的unexpectedFlag和dealStatus值来选择数据的。我们还让tradeDate成ؓqo器的必要属性(Z使用数据库烦引,每个搜烦qo器都应该有必要属性)?/p> <p>鉴于q一点,我们依次使用unexpectedFlag、dealStatus、tradeDate和isold构造了一个复合烦引。两个UI搜烦器都能共用它。(序很重要,如果你的谓语以不同的序指定q些属性或在它们前|列了其他属性,数据库就不会选择该复合烦引。)</p> <p>后端搜烦器和UI搜烦器区别太大,因此我们不得不ؓ它构造另一个复合烦引,依次使用isold、participantCode和transactionType?/p></blockquote> <h4>4.6.2l定参数 vs.字符串拼?/h4> <p>既可以用绑定参数构造HQL的WHERE子句Q也可以使用字符串拼接的ҎQ该军_Ҏ能会有一定媄响。用绑定参数的原因是让数据库一ơ解析SQLQ对后箋的重复请求复用生成好的执行计划,q样做节省了CPU旉和内存。然而,到最优的数据讉K效率Q不同的l定值可能需要不同的SQL执行计划?/p> <p>例如Q一段数据范围可能只返回数据总量?%Q而一大段数据范围可能q回数据总量?0%。前者用烦引更好,而后者则最好用全表扫描?/p> <p>OLTP使用l定参数Q数据仓库用字W串拼接Q因为OLTP通常在一个事务中重复插入和更新数据,只取量数据Q数据仓库通常只有量SQL查询Q有一个确定的执行计划比节省CPU旉和内存更为重要?/p> <p>要是你知道你的OLTP搜烦对不同绑定值应该用相同执行计划又该怎么办呢Q?/p> <p>Oracle 9i及以后版本在W一ơ调用绑定参数ƈ生成执行计划时能探出参数倹{后l调用不会再探测Q而是重用之前的执行计划?/p> <h4>4.6.3聚合及排?/h4> <p>你可以在数据库中q行聚合?#8220;order by”Q也可以在应用程序的服务层中事先加蝲所有数据然后做聚合?#8220;order by”操作。推荐用前者,因ؓ数据库在q方面通常会比你的应用E序做得好。此外,q样做还能节省网l带宽,q也是一U拥有跨数据库移植性的做法?/p> <p>当你的应用程序对数据聚合和排序有HQL不支持的特定业务规则旉外?/p> <h4>4.6.4覆盖抓取{略</h4> <p>详见<strong>4.7.1?/strong>?/p> <h4>4.6.5本地查询</h4> <p>本地查询调优其实q不直接与HQL有关。但HQL的确可以让你直接向底层数据库传递本地查询。我们ƈ不徏议这么做Q因为本地查询在数据库间不可UL?/p> <h3>4.7抓取{略调优</h3> <p>抓取{略军_了在应用E序需要访问关联对象时QHibernate以何U方式以及何时获取关联对象。HRD中的<a ><font color="#0b59b2">W?0?#8220;改善性能”</font></a>对该主题作了很好的阐qͼ我们在此关注它的用方法?/p> <h4>4.7.1覆盖抓取{略</h4> <p>不同的用户可能会有不同的数据抓取要求。Hibernate允许在两个地方定义数据抓取策略,一处是在映元数据中,另一处是在HQL或Criteria中覆盖它?/p> <p>常见的做法是Z主要的抓取用例在映射元数据中定义默认抓取{略Q针对少数用例在HQL和Criteria中覆盖抓取策略?/p> <p>假设pojoA和pojoB是父子关pd例。如果根据业务规则,只是偶尔需要从实体两端加蝲数据Q那你可以声明一个gq加载集合或代理抓取Qproxy fetchingQ。当你需要从实体两端获取数据Ӟ可以用立x取(eager fetchingQ覆盖默认策略,例如使用HQL或Criteria配置q接抓取Qjoin fetchingQ?/p> <p>另一斚wQ如果业务规则在大多数时候需要从实体两端加蝲数据Q那么你可以声明立即抓取q在Criteria中设|gq加载集合或代理抓取来覆盖它QHQL目前q不支持q样的覆盖)?/p> <h4>4.7.2 N+1模式或是反模式?</h4> <p>select抓取会导致N+1问题。如果你知道自己L需要从兌中加载数据,那么p始终使用q接抓取。在下面两个场景中,你可能会把N+1视ؓ一U模式而非反模式?/p> <p>W一U场景,你不知道用户是否会访问关联对象。如果他/Ҏ有访问,那么你赢了;否则你仍焉要额外的Nơselect SQL语句。这是一Uo人左右ؓ隄局面?/p> <p>W二U场景,pojoA和很多其他POJO有one-to-many兌Q例如pojoB和pojoC。用立即的内连接或外连接抓取会在结果集中将pojoA重复很多ơ。当pojoA中有很多非空属性时Q你不得不将大量数据加蝲到持久层中。这U加载需要很多时_既有|络带宽的原因,如果Hibernate的会话是有状态的Q其中也会有会话~存的原因(内存消耗和GC暂停Q?/p> <p>如果你有一个很长的one-to-many兌链,例如从pojoA到pojoB到pojoC以此cLQ情况也是类似的?/p> <p>你也怼M用HQL中的DISTINCT关键字或Cirteria中的distinct功能或是Java的Set接口来消除重复数据。但所有这些都是在HibernateQ在持久层)中实现的Q而非数据库中?/p> <p>如果Z你的|络和内存配|的试表明N+1性能更好Q那么你可以使用扚w抓取、subselect抓取或二U缓存来做进一步调优?/p> <blockquote> <p><strong>范例8</strong></p> <p>以下是一个用批量抓取的HBM文g片段Q?/p><pre><<font color="#0080ff">class</font> <font color="#800000">name</font>=<em>"<font color="#0080ff">pojoA</font>" </em><font color="#800000">table</font>=<em>"<font color="#0080ff">pojoA</font>"</em>> … <<font color="#0080ff">set</font> <font color="#800000">name</font>=<em>"<font color="#0080ff">pojoBs</font>"</em> <font color="#800000">fetch</font>=<em>"<font color="#0080ff">select</font>"</em> <font color="#800000">batch-size</font>=<em>"<font color="#0080ff">10</font>"</em>> <<font color="#0080ff">key</font> <font color="#800000">column</font>=<em>"<font color="#0080ff">pojoa_id</font>"</em>/> … </<font color="#0080ff">set</font>> </<font color="#0080ff">class</font>> </pre> <p>以下是多端pojoB生成的SQLQ?/p><pre><strong><font color="#800000">select</font></strong> … <strong><font color="#800000">from</font></strong> pojoB <strong><font color="#800000">where</font></strong> pojoa_id <strong><font color="#800000">in</font></strong>(?,?,?,?,?, ?,?,?,?,?);</pre> <p>问号数量与batch-size值相{。因此Nơ额外的关于pojoB的select SQL语句被减到了N/10ơ?/p> <p>如果?small><strong><font color="#800000">fetch</font>=<em>"<font color="#0080ff">select</font>"</em></strong></small>替换?small><strong><font color="#800000">fetch</font>=<em>"<font color="#0080ff">subselect</font>"</em></strong></small>QpojoB生成的SQL语句是q样的:</p><pre><strong><font color="#800000">select</font></strong> … <strong><font color="#800000">from</font></strong> pojoB <strong><font color="#800000">where</font></strong> pojoa_id <strong><font color="#800000">in</font></strong>(<strong><font color="#800000">select</font></strong> id <strong><font color="#800000">from</font></strong> pojoA <strong><font color="#800000">where</font></strong> …); </pre> <p>管Nơ额外的select减少?ơ,但这只在重复q行pojoA的查询开销很低时才有好处?/p> <p>如果pojoA中的pojoB集合很稳定,或pojoB有pojoA的many-to-one兌Q而且pojoA是只d用数据,那么你可以用二U缓存来~存pojoA以消除N+1问题Q?strong>4.8.1?/strong>中有一个例子)?/p></blockquote> <h4>4.7.3延迟属性抓?/h4> <p>除非有一张拥有很多你不需要的字段的遗留表Q否则不应该使用q种抓取{略Q因为它的gq属性分l会带来额外的SQL?/p> <p>在业务分析和设计q程中,你应该将不同数据获取或修改分l放C同的领域对象实体中,而不是用这U抓取策略?/p> <p>如果不能重新设计遗留表,可以使用HQL或Criteria提供的投影功能来获取数据?/p> <h4>4.8 二~存调优</h4> <p>HRD<a ><font color="#0b59b2">W?0.2?“二~存”</font></a>中的描述对大多数开发者来说过于简单,无法做出选择?.3版及以后版本不再推荐使用Z“CacheProvider”的缓存,而用Z“RegionFactory”的缓存,q也让h更糊涂了。但是就是最新的3.5参考文档也没有提及如何使用新缓存方法?/p> <p>Z下述考虑Q我们将l箋x于老方法:</p> <ul><li>所有流行的Hibernate二~存提供商中只有<a ><font color="#0b59b2">JBoss Cache 2</font></a>?a ><font color="#0b59b2">Infinispan 4</font></a>?a ><font color="#0b59b2">Ehcache 2</font></a>支持新方法?a ><font color="#0b59b2">OSCache</font></a>?a ><font color="#0b59b2">SwarmCache</font></a>?a ><font color="#0b59b2">Coherence</font></a>?a ><font color="#0b59b2">Gigaspaces XAP-Data Grid</font></a>只支持老方法?/li><li>两种Ҏq相同?lt;cache>配置。例如,它们仍旧使用相同的usage属性?#8220;transactional|read-write|nonstrict-read-write|read-only”?/li><li>多个cache-region适配器仍然内|老方法的支持Q理解它能帮助你快速理解新Ҏ?</li></ul> <h4>4.8.1 ZCacheProvider的缓存机?/h4> <p>理解该机制是做出合理选择的关键。关键的c?接口是CacheConcurrencyStrategy和它针对4中不同缓存用的实现c,q有EntityUpdate/Delete/InsertAction?/p> <p>针对q发~存讉KQ有三种实现模式Q?/p> <ul><li><strong>针对“read-only”的只L式?/strong> <p>无论是锁q是事务都没影响Q因为缓存自数据从数据库加蝲后就不会改变?/p></li><li><strong>针对“read-write”?#8220;nonstrict-read-write”的非事务感知Qnon-transaction-awareQ读写模式?/strong> <p>对缓存的更新发生在数据库事务完成后。缓存需要支持锁?/p></li><li><strong>针对“transactional”的事务感知读写?/strong> <p>对缓存和数据库的更新被包装在同一个JTA事务中,q样~存与数据库L保持同步的。数据库和缓存都必须支持JTA。尽缓存事务内部依赖于~存锁,但Hibernate不会昑ּ调用M的缓存锁函数?/p></li></ul> <p>以数据库更新Z。EntityUpdateAction对于事务感知d?#8220;read-write”的非事务感知dQ还?#8220;nonstrict-read-write”的非事务感知d相应有如下调用序列:</p> <ul><li><strong>在一个JTA事务中更新数据库Q在同一个事务中更新~存?/strong></li><li><strong>软锁~存Q在一个事务中更新数据库;在上一个事务成功完成后更新~存Q否则释放Y锁?/strong> <p>软锁只是一U特定的~存值失效表q方式,在它获得新数据库值前L其他事务d~存。那些事务会转而直接读取数据库?/p> <p>~存必须支持锁;事务支持则不是必ȝ。如果缓存是一个集,“更新~存”的调用会新值推送给所有副本,q通常被称?#8220;推(pushQ?#8221;更新{略?/p></li><li><strong>在一个事务中更新数据库;在上一个事务完成前清除缓存;Z安全赯Q无Z务成功与否,在事务完成后再次清除~存?/strong> <p>既不需要支持缓存锁Q也不需要支持事务。如果是~存集群Q?#8220;清除~存”调用会让所有副本都失效Q这通常被称?#8220;拉(pullQ?#8221;更新{略?/p></li></ul> <p>对于实体的删除或插入动作Q或者集合变_调用序列都是怼的?/p> <p>实际上,最后两个异步调用序列仍能保证数据库和缓存的一致性(基本是“read committed”的隔MU别Q,q要归功于第二个序列中的软锁?#8220;更新数据?#8221;后的“更新~存”Q还有最后一个调用序列中的悲?#8220;清除~存”?/p> <p>Z上述分析Q我们的是: </p> <ul><li>如果数据是只ȝQ例如引用数据,那么L使用“read-only”{略Q因为它是最单、最高效的策略,也是集群安全的策略?/li><li>除非你真的想缓存更新和数据库更新放在一个JTA事务里,否则不要使用“transactional”{略Q因为JTA需要O长的两阶D|交处理,q导致它基本是性能最差的{略? <p>依笔者看来,二~存q一U数据源Q因此用JTA也未必合理。实际上最后两个调用序列在大多数场景下是个不错的替代方案,q要归功于它们的数据一致性保障?/p></li><li>如果你的数据d多或者很有q发~存讉K和更斎ͼ那么可以使用“nonstrict-read-write”{略。感谢它的轻量“?#8221;更新{略Q它通常是性能W二好的{略?/li><li>如果你的数据是又d写的Q那么?#8220;read-write”{略。这通常是性能倒数W二的策略,因ؓ它要求有~存锁,~存集群中用重量?#8220;?#8221;更新{略?</li></ul> <blockquote> <p><strong>范例9</strong></p> <p>以下是一个ISO收费cd的HBM文g片段Q?/p><pre><<font color="#0080ff">class</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">IsoChargeType</font>"></em>    <<font color="#0080ff">property</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">isoId</font>"</em> <font color="#800000">column</font>=<em>"<font color="#0000ff">ISO_ID</font>"</em> <font color="#800000">not-null</font>=<em>"<font color="#0000ff">true</font>"</em>/>    <<font color="#0080ff">many-to-one</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">estimateMethod</font>"</em> <font color="#800000">fetch</font>=<em>"<font color="#0000ff">join</font>"</em> <font color="#800000">lazy</font>=<em>"<font color="#0000ff">false</font>"</em>/>    <<font color="#0080ff">many-to-one</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">allocationMethod</font>"</em> <font color="#800000">fetch</font>=<em>"<font color="#0000ff">join</font>"</em> <font color="#800000">lazy</font>=<em>"<font color="#0000ff">false</font>"</em>/>    <<font color="#0080ff">many-to-one</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">chargeTypeCategory</font>"</em> <font color="#800000">fetch</font>=<em>"<font color="#0000ff">join</font>"</em> <font color="#800000">lazy</font>=<em>"<font color="#0000ff">false</font>"</em>/> </<font color="#0080ff">class</font>> </pre> <p>一些用户只需要ISO收费cd本nQ一些用h需要ISO收费cdQ还需要它的三个关联对象。简单v见,开发者会立即加蝲所有三个关联对象。如果项目中没h负责Hibernate调优Q这是很常见的?/p> <p><strong>4.7.1?/strong>中讲q了最好的Ҏ。因为所有的兌对象都是只读引用数据Q另一U方法是使用延迟抓取Q打开q些对象的二U缓存以避免N+1问题。实际上前一U方法也能从引用数据~存中获益?/p> <p>因ؓ大多数项目都有很多被其他数据引用的只d用数据,上述两种Ҏ都能改善全局pȝ性能?/p></blockquote> <h4>4.8.2 RegionFactory</h4> <p>下表是新老两U方法中对应的主要类/接口Q? <table border="1" cellspacing="0" cellpadding="0"> <tbody> <tr> <td valign="top" width="295"> <p><strong>新方?/strong></p></td> <td valign="top" width="348"> <p><strong>老方?/strong></p></td></tr> <tr> <td valign="top" width="295"> <p>RegionFactory</p></td> <td valign="top" width="348"> <p>CacheProvider</p></td></tr> <tr> <td valign="top" width="295"> <p>Region</p></td> <td valign="top" width="348"> <p>Cache</p></td></tr> <tr> <td valign="top" width="295"> <p>EntityRegionAccessStrategy</p></td> <td valign="top" width="348"> <p>CacheConcurrencyStrategy</p></td></tr> <tr> <td valign="top" width="295"> <p>CollectionRegionAccessStrategy</p></td> <td valign="top" width="348"> <p>CacheConcurrencyStrategy</p></td></tr></tbody></table></p> <p>W一个改q是RegionFactory构徏了特定的RegionQ例如EntityRegion和TransactionRegionQ而不是用一个通用的访问Region。第二个改进是对于特定缓存的“usage”属性|Region要求构徏自己的访问策略,而不是所有Region都一直用CacheConcurrencyStrategy?U实现?/p> <p>要用新ҎQ应该设|factory_class而非provider_class配置属性。以Ehcache 2.0ZQ?/p><pre><property name="hibernate.cache.region.factory_class">         net.sf.ehcache.hibernate.EhCacheRegionFactory  </property></pre> <p>其他相关的Hibernate~存配置都和老方法一栗?/p> <p>新方法也能向后兼定w留方法。如果还是只配了CacheProviderQ新Ҏ中将使用下列自说明(self-explanatoryQ适配器和桥隐式地调用老的接口/c:</p> <p>RegionFactoryCacheProviderBridge、EntityRegionAdapter、CollectionRegionAdapter、QueryResultsRegionAdapter、EntityAccessStrategyAdapter和CollectionAccessStrategyAdapter</p> <h4>4.8.3 查询~存</h4> <p>二~存也能~存查询l果。如果查询开销很大而且要重复运行,q也会很有帮助?/p> <h3>4.9扚w处理调优</h3> <p>大多数Hibernate的功能都很适合那些每个事务都通常只处理少量数据的OLTPpȝ。但是,如果你有一个数据仓库或者事务需要处理大量数据,那么另当别Z?/p> <h5>4.9.1使用有状态会话的非DML风格批处?/h5> <p>如果你已l在使用常规会话了,那这是最自然的方法。你需要做三g事:</p> <ul><li>配置下列3个属性以开启批处理Ҏ: <pre>  hibernate.jdbc.batch_size 30   hibernate.jdbc.batch_versioned_data true   hibernate.cache.use_second_level_cache false</pre> <p>batch_size讄为正g开启JDBC2的批量更斎ͼHibernate的徏议值是5?0。基于我们的试Q极低值和极高值性能都很差。只要取值在合理范围内,区别只有几U而已。如果网l够快,q个l果是一定的?/p> <p>W二个配|设为trueQ这要求JDBC驱动在executeBatch()Ҏ中返回正的行数。对于Oracle用户而言Q批量更新时不能其设ؓtrue。请阅读Oracle的《JDBC Developer’s Guide and Reference》中?#8220;<a ><font color="#0b59b2">标准批处理的Oracle实现中的更新计数</font></a>”Q?a ><font color="#0b59b2">Update Counts in the Oracle Implementation of Standard Batching</font></a>Q以获得更多详细信息。因为它Ҏ量插入来说还是安全的Q所以你可以为批量插入创建单独的专用数据源。最后一个配|项是可选的Q因Z可以在会话中昑ּ关闭二~存?/p></li><li>像如下范例中那样定期hQflushQƈ清除一U会话缓存: <pre> Session session = sessionFactory.openSession();  Transaction tx = session.beginTransaction(); <p> for ( int i=0; i<100000; i++ ) {<br />     Customer customer = new Customer(.....);<br />     //if your hibernate.cache.use_second_level_cache is true, call the following:<br />     session.setCacheMode(CacheMode.IGNORE);<br />     session.save(customer);<br />     if (i % 50 == 0) { //50, same as the JDBC batch size<br />     //flush a batch of inserts and release memory:<br />     session.flush();<br />     session.clear();<br />     }<br /> }<br /> tx.commit();<br /> session.close();</p></pre> <p>批处理通常不需要数据缓存,否则你会内存耗尽q大量增加GC开销。如果内存有限,那这U情况会很明显?/p></li><li>L批量插入嵌套在事务中?</li></ul> <p>每次事务修改的对象数量越就意味着会有更多数据库提交,正如<strong>4.5?/strong>所q每ơ提交都会带来磁盘相关的开销?/p> <p>另一斚wQ每ơ事务修改的对象数量多意味着锁定变更旉长Q同时数据库需要更大的redo log?/p> <h4>4.9.2使用无状态会话的非DML风格批处?/h4> <p>无状态会话执行v来比上一U方法更好,因ؓ它只是JDBC的简单包装,而且可以l开很多常规会话要求的操作。例如,它不需要会话缓存,也不和Q何二U缓存或查询~存有交互?br />然而它的用法ƈ不简单。尤其是它的操作q不会联到所兌的实例上Q你必须自己来处理它们?/p> <h4>4.9.3 DML风格</h4> <p>使用DML风格的插入、更新或删除Q你直接在数据库中操作数据,q和前两U方法在Hibernate中操作数据的情况有所不同?/p> <p>因ؓ一个DML风格的更新或删除相当于前两种Ҏ中的多个单独的更新或删除Q所以如果更新或删除中的WHERE子句暗示了恰当的数据库烦引,那么使用DML风格的操作能节省|络开销Q执行得更好?/p> <p>强烈l合使用DML风格操作和无状态会话。如果用有状态会话,不要忘记在执行DML前清除缓存,否则Hibernate会更新或清除相关缓存(见下面的范例10Q?/p> <h4>4.9.4扚w加蝲</h4> <p>如果你的HQL或Criteria会返回很多数据,那么要注意两件事Q?/p> <ul><li>用下列配|开启批量抓取特性: <pre>hibernate.jdbc.fetch_size 10</pre> <p>fetch_size讄为正值将开启JDBC扚w抓取Ҏ。相对快速网l,在慢速网l中q一Ҏ为重要。Oracle的经验值是10。你应该Z自己的环境进行测试?/p></li><li>在用上qCQ一Ҏ旉要关闭缓存,因ؓ扚w加蝲一般是一ơ性Q务。受限于内存定wQ向~存中加载大量数据通常也意味着它们很快会被清除出去Q这会增加GC开销?</li></ul> <blockquote> <p><strong>范例10</strong></p> <p>我们有一个后CQ务,分段加蝲大量的IsoDeal数据用于后箋处理。我们还会在分段数据交给下游pȝ处理前将其更Cؓ处理中状态。最大的一D|50万行数据。以下是原始代码中截取出来的一D:</p><pre>Query query = session.createQuery("<font color="#0000ff">FROM IsoDeal d WHERE chunk-clause</font>"); query.setLockMode(<font color="#0000ff">"d"</font>, LockMode.<em><font color="#0000ff">UPGRADE</font></em>); //for Inprocess status update List<IsoDeal> isoDeals = query.list(); for (IsoDeal isoDeal : isoDeals) { //update status to Inprocess    isoDeal.setStatus<font color="#0000ff">("Inprocess"</font>); } return isoDeals; </pre> <p>包含上述代码的方法加上了Spring 2.5声明式事务的注解。加载ƈ更新50万行数据大约׃10分钟。我们识别出了以下这些问题:</p> <ul><li>׃会话~存和二U缓存的原因Q系l会频繁地内存溢出?/li><li>q没有内存溢出Q当内存消耗很高时GC的开销也会很大?/li><li>我们q未讄fetch_size?/li><li>q我们讄了batch_sizeQfor循环也创Z太多update SQL语句?</li></ul> <p>不幸的是Spring 2.5不支持Hibernate无状态会话,所以我们只能关闭二U缓存;讄fetch_sizeQ用DML风格的更新来代替for循环Q以此改善性能?/p> <p>但是Q执行时间还是要6分钟。将Hibernate的日志别调成trace后,我们发现是更C话缓存造成了g时。通过在DML更新前清除会话缓存,我们时间羃短到?分钟Q全部都是将数据加蝲C话缓存中p的时间?/p></blockquote> <h3>4.10 SQL生成调优</h3> <p>本节向你展C如何减SQL生成的数量?/p> <h4>4.10.1 N+1抓取问题</h4> <p>“select抓取”{略会导致N+1问题。如?#8220;q接抓取”{略适合你的话,你应该始l用该{略避免N+1问题?/p> <p>但是Q如?#8220;q接抓取”{略执行效果不理惻I像<strong>4.7.2?/strong>中那P你可以?#8220;subselect抓取”?#8220;扚w抓取”?#8220;延迟集合抓取”来减所需的额外SQL语句数?/p> <h4>4.10.2 Insert+Update问题</h4> <blockquote> <p><strong>范例11</strong></p> <p>我们的ElectricityDeal与DealCharge有单向one-to-many兌Q如下列HBM文g片段所C:</p><pre><<font color="#0080ff">class</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">ElectricityDeal</font>"</em>        <font color="#800000">select-before-update</font>=<em>"<font color="#0000ff">true</font>"</em> <font color="#800000">dynamic-update</font>=<em>"<font color="#0000ff">true</font>"</em>        <font color="#800000">dynamic-insert</font>=<em>"<font color="#0000ff">true</font>"</em>>     <font color="#0080ff"><id</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">key</font>"</em> <font color="#800000">column</font>=<em>"<font color="#0000ff">ID</font>"</em>>         <font color="#0080ff"><generator</font> <font color="#800000">class</font>=<em>"<font color="#0000ff">sequence</font>"</em>>             <font color="#0080ff"><param</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">sequence</font>"</em>>SEQ_ELECTRICITY_DEALS<<font color="#0080ff">/param</font>>         <font color="#0080ff"></generator></font>     <font color="#0080ff"></id><br />    …<br />    <set</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">dealCharges</font>" </em><font color="#800000">cascade</font>=<em>"<font color="#0000ff">all-delete-orphan</font>"></em>         <font color="#0080ff"><key </font><font color="#800000">column</font>=<em>"<font color="#0000ff">DEAL_KEY</font>"</em> <font color="#800000">not-null</font>=<em>"<font color="#0000ff">false</font>"</em> <font color="#800000">update</font>=<em>"<font color="#0000ff">true</font>"</em>              <font color="#800000">on-delete</font>=<em>"<font color="#0000ff">noaction</font>"</em>/>         <font color="#0080ff"><one-to-many</font> <font color="#0000ff">class</font>=<em>"<font color="#0000ff">DealCharge</font>"</em>/>     <font color="#0080ff"></set> </class></font> </pre></blockquote> <p>?#8220;key”元素中,“not-null”?#8220;update”对应的默认值是false和trueQ上qC码ؓ了明这些取|它们写了出来?/p> <p>如果你想创徏一个ElectricityDeal和十个DealChargeQ会生成如下SQL语句Q?/p> <ul><li>1句ElectricityDeal的插入语句;</li><li>10句DealCharge的插入语句,其中不包括外?#8220;DEAL_KEY”Q?/li><li>10句DealCharge字段“DEAL_KEY”的更新语句?</li></ul> <p>Z消除那额外的10句更新语句,可以在那10句DealCharge插入语句中包?#8220;DEAL_KEY”Q你需要将“not-null”?#8220;update”分别修改为true和false?/p> <p>另一U做法是使用双向或many-to-one兌Q让DealCharge来管理关联?/p> <h4>4.10.3 更新前执行select</h4> <p>在范?1中,我们为ElectricityDeal加上了select-before-updateQ这会对瞬时QtransientQ对象或分离QdetachedQ对象生额外的select语句Q但却能避免不必要的数据库更新?/p> <p>你应该做Z些权衡,如果对象没多属性,不需要防止不必要的数据库更新Q那么就不要使用该特性,因ؓ你那些有限的数据既没有太多网l传输开销Q也不会带来太多数据库更新开销?/p> <p>如果对象的属性较多,例如是一张大的遗留表Q那你应该开启该Ҏ,?#8220;dynamic-update”l合使用以避免太多数据库更新开销?/p> <h4>4.10.4 U联删除</h4> <p>在范?1中,如果你想删除1个ElectricityDeal和它?00个DealChargeQHibernate会对DealCharge?00ơ删除?/p> <p>如果?#8220;on-delete”修改?#8220;cascade”QHibernate不会执行DealCharge的删除动作;而是让数据库ҎON CASCADE DELETEU束自动删除?00个DealCharge。不q,需要让DBA开启ON CASCADE DELETEU束Q大多数DBA不愿意这么做Q因Z们想避免父对象的意外删除U联到它的依赖对象上。此外,q要注意Q该Ҏ会l过Hibernate对版本数据(versioned dataQ的常用乐观锁策略?/p> <h4>4.10.5 增强的序列标识符生成?/h4> <p>范例11中用Oracle的序列作为标识符生成器。假设我们保?00个ElectricityDealQHibernate会将下面的SQL语句执行100ơ来获取下一个可用的标识W:</p><pre><strong><font color="#800000">select</font></strong> SEQ_ELECTRICITY_DEALS.NEXTVAL <strong><font color="#800000">from</font></strong> dual; </pre> <p>如果|络不是很快Q那q无疑会降低效率?.2.3及后l版本中增加了一个增强的生成?#8220;SequenceStyleGenerator”Q它带了两个优化器:hilo和pooled。尽HRD?a ><font color="#0b59b2">W??#8220;基础O/R映射”</font></a> 讲到了这两个优化器,不过内容有限。两个优化器都用了HiLo法Q该法生成的标识符{于Hi值加上Lo|其中Hig表组PLo值顺序且重复C1q代到最大组大小Q组号在Lo?#8220;转回?#8221;1时加1?/p> <p>假设l大是5Q可以用max_lo或increment_size参数来表C)Q下面是个例子:</p> <p><a ><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="" src="http://www.infoq.com/resource/articles/hibernate_tuning-ii/zh/resources/table1.jpg" _href="img://table.jpg" _p="true" /></a></p> <ul><li>hilo优化? <p>l号取自数据库序列的下一个可用|Hi值由Hibernate定义Q是l号乘以increment_size参数倹{?/p></li><li>pooled优化? <p>Hi值直接取自数据库序列的下一个可用倹{数据库序列的增量应该设|ؓincrement_size参数倹{?/p></li></ul> <p>直到内存l中的D尽后,两个优化器才会去讉K数据库,上面的例子每5个标识值符讉K一ơ数据库。用hilo优化器时Q你的序列不能再被其他应用程序用,除非它们使用与Hibernate相同的逻辑。用pooled优化器,在其他应用程序用同一序列时则相当安全?/p> <p>两个优化器都有一个问题,如果Hibernate崩溃Q当前组内的一些标识符值就会丢失,然而大多数应用E序都不要求拥有q箋的标识符|如果你的数据库,比方说OracleQ缓存了序列|当它崩溃时你也会丢失标识W|?/p> <p>如果在范?1中用pooled优化器,新的id配置如下Q?/p><pre><font color="#0080ff"><id</font> <font color="#800000">name</font>=<em>"key"</em> <font color="#800000">column</font>=<em>"<font color="#0000ff">ID"</font></em><font color="#0000ff">></font> <font color="#0080ff"><generator</font> <font color="#800000">class</font>=<font color="#0000ff"><em>"org.hibernate.id.enhance</em>.<em>SequenceStyleGenerator"</em>><br /></font> <font color="#0080ff"><param</font> <font color="#800000">name</font>=<font color="#0000ff"><em>"sequence_name"</em>></font>SEQ_ELECTRICITY_DEALS<font color="#0080ff"></param></font> <font color="#0080ff"><param</font> <font color="#800000">name</font>=<font color="#0000ff"><em>"initial_value"</em>></font>0<font color="#0080ff"></param></font> <font color="#0080ff"><param</font> <font color="#800000">name</font>=<font color="#0000ff"><em>"increment_size"</em>></font>100<font color="#0080ff"></param></font> <font color="#0080ff"><param</font> <font color="#800000">name</font>=<font color="#0000ff"><em>"optimizer "</em>></font>pooled<font color="#0080ff"></param></font> <font color="#0080ff"></generator></font> <font color="#0080ff"></id></font> </pre> <h2>5 ȝ</h2> <p>本文늛了大多数你在Hibernate应用E序调优时会觉得很有用的调优技巧,其中的大多数旉都在讨论那些行之有效却缺乏文的调优主题Q例如承映、二U缓存和增强的序列标识符生成器?/p> <p>它还提到了一些Hibernate调优所必需的数据库知识。一些范例中包含了你可能遇到的问题的实际解决Ҏ?/p> <p>除此之外Q值得一提的是Hibernate也可以和In-Memory Data GridQIMDGQ一起用,例如Oracle的Coherance或GigaSpaces IMDGQ这能让你的应用E序辑ֈ毫秒U别?/p> <h2>6 资源</h2> <p><a name="ref1"><u><font color="#0b59b2">[1] </font></u></a><a ><font color="#0b59b2">Latest Hibernate Reference Documentation on jboss.com</font></a><a name="zw-12b8a5a1c58woCkZs3ee8a"></a></p> <p>[2] Oracle 9i Performance Tuning Guide and Reference</p> <p>[3] <a ><font color="#0b59b2">Performance Engineering on Wikipedia</font></a><a name="zw-12b8a5a1c5976Ow-3ee8a"></a></p> <p>[4] <a ><font color="#0b59b2">Program Optimization on Wikipedia</font></a><a name="zw-12b8a5a1c5aB_muaJ3ee8a"></a></p> <p>[5] <a ><font color="#0b59b2">Pareto Principle (the 80/20 rule) on Wikipedia</font></a><a name="zw-12b8a5a1c5awlS2Mh3ee8a"></a></p> <p>[6] <a ><font color="#0b59b2">Premature Optimization on acm.org</font></a><a name="zw-12b8a5a1c5betO6_a3ee8a"></a></p> <p>[7] <a ><font color="#0b59b2">Java Performance Tuning by Jack Shirazi</font></a><a name="zw-12b8a5a1c5cGOWnf3ee8a"></a></p> <p>[8] <a ><font color="#0b59b2">The Law of Leaky Abstractions by Joel Spolsky</font></a><a name="zw-12b8a5a1c5dd-0Cfh3ee8a"></a></p> <p>[9] <a ><font color="#0b59b2">Hibernate’s StatisticsService Mbean configuration with Spring</font></a><a name="zw-12b8a5a1c5dAhfm5n3ee8a"></a></p> <p>[10] <a ><font color="#0b59b2">JProbe by Quest Software</font></a><a name="zw-12b8a5a1c5eZEEGyf3ee8a"></a></p> <p>[11] <a ><font color="#0b59b2">Java VisualVM</font></a><a name="zw-12b8a5a1c5ftkFIlr3ee8a"></a></p> <p>[12] <a ><font color="#0b59b2">Column-oriented DBMS on Wikipedia</font></a><a name="zw-12b8a5a1c60O1lu03ee8a"></a></p> <p>[13] <a ><font color="#0b59b2">Apache DBCP BasicDataSource</font></a><a name="zw-12b8a5a1c60WLNaFZ3ee8a"></a></p> <p>[14] <a ><font color="#0b59b2">JDBC Connection Pool by Oracle</font></a><a name="zw-12b8a5a1c61bldeBA3ee8a"></a></p> <p>[15] <a ><font color="#0b59b2">Connection Failover by Oracle</font></a><a name="zw-12b8a5a1c62xzlPft3ee8a"></a></p> <p>[16] <a ><font color="#0b59b2">Last Resource Commit Optimization (LRCO)</font></a><a name="zw-12b8a5a1c63r48X9-3ee8a"></a></p> <p>[17] <a ><font color="#0b59b2">GigaSpaces for Hibernate ORM Users</font></a><a name="zw-12b8a5a1c63PesI8V3ee8a"></a></p><br /><br /> <img src ="http://www.aygfsteel.com/zstop/aggbug/352568.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zstop/" target="_blank">...</a> 2011-06-18 12:03 <a href="http://www.aygfsteel.com/zstop/archive/2011/06/18/352568.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]加速你的Hibernate引擎Q上Q?/title><link>http://www.aygfsteel.com/zstop/archive/2011/06/18/352567.html</link><dc:creator>...</dc:creator><author>...</author><pubDate>Sat, 18 Jun 2011 03:59:00 GMT</pubDate><guid>http://www.aygfsteel.com/zstop/archive/2011/06/18/352567.html</guid><wfw:comment>http://www.aygfsteel.com/zstop/comments/352567.html</wfw:comment><comments>http://www.aygfsteel.com/zstop/archive/2011/06/18/352567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.aygfsteel.com/zstop/comments/commentRss/352567.html</wfw:commentRss><trackback:ping>http://www.aygfsteel.com/zstop/services/trackbacks/352567.html</trackback:ping><description><![CDATA[<a >http://www.infoq.com/cn/articles/hibernate_tuning</a><br /><br /> <h2>1.引言</h2> <p><a ><font color="#0b59b2">Hibernate</font></a>是最行的对象关pL(ORMQ引擎之一Q它提供了数据持久化和查询服务?/p> <div id="wmqeeuq" class="vendor-content-box-float"><br />2.Hibernate性能调优</div> <p>调优是一个P代的、持l进行的q程Q涉及Y件开发生命周期(SDLCQ的所有阶Dc在一个典型的使用Hibernateq行持久化的Java EE应用E序中,调优会涉及以下几个方面:</p> <ul><li>业务规则调优</li><li>设计调优</li><li>Hibernate调优</li><li>Java GC调优</li><li>应用E序容器调优</li><li>底层pȝ调优Q包括数据库和OS?</li></ul> <p>没有一套精心设计的Ҏ去q行以上调优是非常耗时的,而且很可能收效甚微。好的调优方法的重要部分是ؓ调优内容划分优先U。可以用Pareto定律Q又U?#8220;80/20法则”Q来解释q一点,即通常80%的应用程序性能改善源自?0%的性能问题<sup>[5]</sup>?/p> <p>相比Z盘和网l的讉KQ基于内存和CPU的访问能提供更低的gq和更高的吞吐量。这U基于IO的Hibernate调优与底层系lIO部分的调优应该优先于ZCPU和内存的底层pȝGC、CPU和内存部分的调优?/p> <blockquote> <p><strong>范例1</strong></p> <p>我们调优了一个选择甉|的HQL查询Q把它从30U降C1U以内。如果我们在垃圾回收斚w下功夫,可能收效甚微——也许只有几毫U或者最多几U,相比HQL的改q,GC斚w的改善可以忽略不计?/p></blockquote> <p>好的调优Ҏ的另一个重要部分是军_何时优化<sup>[4]</sup>?/p> <p>U极优化的提倡者主张开始时p行调优,例如在业务规则和设计阶段Q在整个SDLC都持l进行优化,因ؓ他们认ؓ后期改变业务规则和重新设计代价太大?/p> <p>另一zh提倡在SDLC末期q行调优Q因Z们抱怨前期调优经怼让设计和~码变得复杂。他们经常引用Donald Knuth的名a“<em>q早优化是万恶之?/em>”<sup> [6]</sup>?/p> <p>Zq调优和编码需要一些权衡。根据笔者的l验Q适当的前期调优能带来更明智的设计和细致的~码。很多项目就p|在应用程序调优上Q因Z面提到的“q早优化”阶段在被引用时脱M上下文,而且相应的调优不是被推迟得太晚就是投入资源过?/p> <p>但是Q要做很多前期调优也不太可能Q因为没有经q剖析,你ƈ不能定应用E序的瓶颈究竟在何处Q应用程序一般都是这h化的?/p> <p>Ҏ们的多线E企业应用E序的剖析也表现出大多数应用E序q_只有20-50%的CPU使用率。剩余的CPU开销只是在等待数据库和网l相关的IO?/p> <p>Z上述分析Q我们得样一个结论,l合业务规则和设计的Hibernate调优在Pareto定律?0%的那个部分,相应的它们的优先U更高?/p> <p>一U比较实际的做法是:</p> <ol><li>识别Z要瓶颈,可以预见其中多数是Hibernate、业务规则和设计斚w的(其数量视你的调优目标而定Q但三到五个是不错的开端)?/li><li>修改应用E序以便消除q些瓉?/li><li>试应用E序Q然后重复步?Q直到达C的调优目标ؓ止?</li></ol> <p>你能在Jack Shirazi的《Java Performance Tuning?<sup>[7]</sup>一书中扑ֈ更多关于性能调优阶段的常见徏议?/p> <p>下面的章节中Q我们会按照调优的大致顺序(列在前面的通常影响最大)去解释一些特定的调优技术?/p> <h2>3. 监控和剖?/h2> <p>没有对Hibernate应用E序的有效监控和剖析Q你无法得知性能瓉以及何处需要调优?/p> <h3>3.1.1 监控SQL生成</h3> <p>管使用Hibernate的主要目的是你从直接用SQL的痛苦中解救出来Qؓ了对应用E序q行调优Q你必须知道Hibernate生成了哪些SQL。JoeSplosky在他的《The Law of Leaky Abstractions》一文中详细描述了这个问题?/p> <p>你可以在log4j中将<strong>org.hibernate.SQL</strong>包的日志U别设ؓDEBUGQ这样便能看到生成的所有SQL。你q可以将其他包的日志U别设ؓDEBUGQ甚至TRACE来定位一些性能问题?/p> <h3>3.1.2 查看Hibernatel计</h3> <p>如果开?strong>hibernate.generate.statistics</strong>QHibernate会导出实体、集合、会话、二U缓存、查询和会话工厂的统计信息,q对通过<strong>SessionFactory.getStatistics()</strong>q行的调优很有帮助。ؓ了简单v见,Hibernateq可以用MBean“<strong>org.hibernate.jmx.StatisticsService</strong>”通过JMX来导出统计信息。你可以<u>在这个网站找到配|范?/u><u> </u><u>?/u></p> <h3>3.1.3 剖析</h3> <p>一个好的剖析工具不仅有利于Hibernate调优Q还能ؓ应用E序的其他部分带来好处。然而,大多数商业工P例如JProbe <sup>[10]</sup>Q都很昂c幸q的是Sun/Oracle的JDK1.6自带了一个名?#8220;Java VisualVM” <sup>[11]</sup>的调试接口。虽然比起那些商业竞争对手,它还相当基础Q但它提供了很多调试和调优信息?/p> <h2>4. 调优技?/h2> <h3>4.1 业务规则与设计调?/h3> <p>管业务规则和设计调优ƈ不属于Hibernate调优的范_但此处的军_对后面Hibernate的调优有很大影响。因此我们特意指Z些与Hibernate调优有关的点?/p> <p>在业务需求收集与调优q程中,你需要知道:</p> <ul><li>数据获取Ҏ包括引用数据(reference dataQ、只L据、读分组Qread groupQ、读取大、搜索条件以及数据分l和聚合?/li><li>数据修改Ҏ包括数据变更、变更组、变更大、无效修改补ѝ数据库Q所有变更都在一个数据库中或在多个数据库中)、变更频率和q发性,以及变更响应和吞吐量要求?/li><li>数据关系Q例如关联(associationQ、泛化(generalizationQ、实玎ͼrealizationQ和依赖QdependencyQ?</li></ul> <p>Z业务需求,你会得到一个最优设计,其中军_了应用程序类型(是OLTPq是数据仓库Q亦或者与其中某一U比较接q)和分层结构(持久层和服务层分离q是合ƈQ,创徏领域对象Q通常是POJOQ,军_数据聚合的地方(在数据库中进行聚合能利用强大的数据库功能Q节省网l带宽;但是除了像COUNT、SUM、AVG、MIN和MAXq样的标准聚合,其他的聚合通常不具有移植性。在应用服务器上q行聚合允许你应用更复杂的业务逻辑Q但你需要先在应用程序中载入详细的数据)?/p> <blockquote> <p><strong>范例2</strong></p> <p>分析员需要查看一个取自大数据表的甉|ISOQIndependent System OperatorQ聚合列表。最开始他们想要显C大多数字段Q尽数据库能在1分钟内做出响应,应用E序也要?0分钟?百万行数据加载到前端UI。经q重新分析,分析员保留了14个字Dc因为去掉了很多可选的高聚合度字段Q从剩下的字D中q行聚合分组q回的数据要很多,而且大多数情况下的数据加载时间也~小C可接受的范围内?/p> <p><strong>范例3</strong></p> <p>q?4?#8220;非标?#8221;QshapedQ表C每时都可以有自己的电量和hQ如果所?4时的电量和h相同Q我们称之ؓ“标准”Q小时会修改时甉|交易Q其中包?个属性:每小时电量和h。v初我们用Hibernate?em>select-before-update</em>Ҏ,是更新24行数据需?4ơ选择。因为我们只需?个属性,而且如果不修改电量或h的话也没有业务规则禁止无效修改,我们关闭了<em>select-before-update</em>Ҏ,避免?4ơ选择?/p></blockquote> <h3>4.2l承映射调优</h3> <p>管l承映射是领域对象的一部分Q出于它的重要性我们将它单独出来。HRD <sup>[1]</sup>中的<a ><font color="#0b59b2">W??#8220;l承映射”</font></a>已经说得很清楚了Q所以我们将xSQL生成和针Ҏ个策略的调优?/p> <p>以下是HRD中范例的cdQ?/p> <p><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="" src="http://www.infoq.com/resource/articles/hibernate_tuning/zh/resources/image1.jpg" _href="img://image1.jpg" _p="true" /><a><br /></a></p> <h4>4.2.1 每个cdơ一张表</h4> <p>只需要一张表Q一条多态查询生成的SQL大概是这LQ?/p><pre>select id, payment_type, amount, currency, rtn, credit_card_type <strong>from</strong> payment</pre> <p>针对具体子类Q例如CashPaymentQ的查询生成的SQL是这LQ?/p><pre>select id, amount, currency <strong>from</strong> payment <strong>where</strong> payment_type=’CASH’ </pre> <p>q样做的优点包括只有一张表、查询简单以及容易与其他表进行关联。第二个查询中不需要包含其他子cM的属性。所有这些特性让该策略的性能调优要比其他{略Ҏ得多。这U方法通常比较适合数据仓库pȝQ因为所有数据都在一张表里,不需要做表连接?/p> <p>主要的缺Ҏ个类层次中的所有属性都挤在一张大表里Q如果有很多子类Ҏ的属性,数据库中׃有太多字D늚取gؓnullQ这为当前基于行的数据库Q用基于列的DBMS的数据仓库处理这个会更好些)的SQL调优增加了难度。除非进行分区,否则唯一的数据表会成为热点,OLTPpȝ通常在这斚w都不太好?/p> <h4>4.2.2每个子类一张表</h4> <p>需?张表Q多态查询生成的SQL如下Q?/p><pre><font color="#800000">select</font> id, payment_type, amount, currency, rtn, credit_card type,         case when c.payment_id <font color="#800000"><strong>is</strong> <strong>not</strong> <strong><font color="#0080ff">null</font></strong> <strong>then</strong></font> 1      when ck.payment_id <font color="#800000"><strong>is</strong> <strong>not</strong> <strong><font color="#0080ff">null</font></strong> <strong>then</strong></font> 2      when cc.payment_id <font color="#800000"><strong>is</strong> <strong>not</strong> <strong><font color="#0080ff">null</font></strong> <strong>then</strong></font> 3      when p.id <font color="#800000"><strong>is</strong> <strong>not</strong> <strong><font color="#0080ff">null</font></strong> <strong>then</strong></font> 0 <font color="#800000"><strong>end</strong> <strong>as</strong></font> clazz <strong><font color="#800000">from</font></strong> payment p <font color="#800000"><strong>left</strong> <strong>join</strong></font> cash_payment c <strong><font color="#800000">on</font></strong> p.id=c.payment_id <font color="#800000"><strong>left join</strong></font>    cheque_payment ck <strong><font color="#800000">on</font></strong> p.id=ck.payment_id <font color="#800000"><strong>left</strong> </font><strong><font color="#800000">join</font> </strong>    credit_payment cc <strong><font color="#800000">on</font></strong> p.id=cc.payment_id; </pre> <p>针对具体子类Q例如CashPaymentQ的查询生成的SQL是这LQ?/p><pre><font color="#800000">select</font> id, payment_type, amount, currency <strong><font color="#800000">from</font></strong> payment p <font color="#800000"><strong>left</strong> <strong>join</strong></font> cash_payment c <strong><font color="#800000">on</font></strong> p.id=c.payment_id; </pre> <p>优点包括数据表比较紧凑(没有不需要的可空字段Q,数据跨三个子cȝ表进行分区,Ҏ使用类的表与其他表q行兌。紧凑的数据表可以针对基于行的数据库做存储块优化Q让SQL执行得更好。数据分区增加了数据修改的ƈ发性(除了类Q没有热点)QOLTPpȝ通常会更好些?/p> <p>同样的,W二个查询不需要包含其他子cȝ属性?/p> <p>~点是在所有策略中它用的表和表连接最多,SQL语句E显复杂Q看看Hibernate动态鉴别器的长CASE子句Q。相比单张表Q数据库要花更多旉调优数据表连接,数据仓库在用该{略旉常不太理想?/p> <p>因ؓ不能跨超cd子类的字D|建立复合索引Q如果需要按q些列进行查询,性能会受影响。Q何子cL据的修改都涉及两张表Q超cȝ表和子类的表?/p> <h4>4.2.3每个具体cM张表</h4> <p>涉及三张或更多的表,多态查询生成的SQL是这LQ?/p><pre><font color="#800000">select</font> p.id, p.amount, p.currency, p.rtn, p. credit_card_type, p.clazz <font color="#800000"><strong>from</strong> (<strong>select</strong></font> id, amount, currency, <strong><font color="#0080ff">null</font></strong> <strong><font color="#800000">as</font></strong> rtn,<strong><font color="#0080ff">null</font></strong> <strong><font color="#800000">as</font></strong> credit_card type, 1 <strong><font color="#800000">as</font></strong> clazz <strong><font color="#800000">from</font></strong> cash_payment <font color="#800000"><strong>union</strong> <strong>all</strong></font> <strong><font color="#800000"> select</font></strong> id, amount, <strong><font color="#0080ff">null</font></strong> <strong><font color="#800000">as</font></strong> currency, rtn,<strong><font color="#0080ff">null</font></strong> <strong><font color="#800000">as</font></strong> credit_card type, 2 <strong><font color="#800000">as</font></strong> clazz <strong><font color="#800000">from</font></strong> cheque_payment <font color="#800000"><strong>union</strong> <strong>all</strong></font> <strong><font color="#800000"> select</font></strong> id, amount, <strong><font color="#0080ff">null</font></strong> <strong><font color="#800000">as</font></strong> currency, <strong><font color="#0080ff">null</font></strong> <strong><font color="#800000">as</font></strong> rtn,credit_card type, 3 <strong><font color="#800000">as</font></strong> clazz <strong><font color="#800000">from</font></strong> credit_payment) p; </pre> <p>针对具体子类Q例如CashPaymentQ的查询生成的SQL是这LQ?/p><pre><font color="#800000">select</font> id, payment_type, amount, currency <strong><font color="#800000">from</font></strong> cash_payment; </pre> <p>优点和上面的“每个子类一张表”{略怼。因c通常是抽象的Q所以具体的三张表是必须的[开头处说的3张或更多的表是必ȝ]QQ何子cȝ数据修改只涉及一张表Q运行v来更快?/p> <p>~点是SQLQfrom子句和union all子查询)太复杂。但是大多数数据库对此类SQL的调优都很好?/p> <p>如果一个类惛_Payment类兌Q数据库无法使用引用完整性(referential integrityQ来实现它;必须使用触发器来实现它。这Ҏ据库性能有些影响?/p> <h4>4.2.4使用隐式多态实现每个具体类一张表</h4> <p>只需要三张表。对于Payment的多态查询生成三条独立的SQL语句Q每个对应一个子cRHibernate引擎通过Java反射扑ևPayment的所有三个子cR?/p> <p>具体子类的查询只生成该子cȝSQL。这些SQL语句都很单,q里׃再阐qC?/p> <p>它的优点和上节类|紧凑数据表、跨三个具体子类的数据分Z及对子类L数据的修攚w只涉及一张表?/p> <p>~点是用三条独立的SQL语句代替了一条联合SQLQ这会带来更多网lIO。Java反射也需要时间。假讑֦果你有一大堆领域对象Q你从最上层的Objectc进行隐式选择查询Q那该需要多长时间啊Q?/p> <p>Ҏ你的映射{略制定合理的选择查询q易事Q这需要你仔细调优业务需求,Z特定的数据场景制定合理的设计决策?/p> <p>以下是一些徏议:</p> <ul><li>设计l粒度的cdơ和_粒度的数据表。细_度的数据表意味着更多数据表连接,相应的查询也会更复杂?/li><li>如非必要Q不要用多态查询。正如上文所C,对具体类的查询只选择需要的数据Q没有不必要的表q接和联合?/li><li>“每个cdơ一张表”Ҏ高ƈ发、简单查询ƈ且没有共享列的OLTPpȝ来说是个不错的选择。如果你想用数据库的引用完整性来做关联,那它也是个合适的选择?/li><li>“每个具体cM张表”Ҏ高ƈ发、复杂查询ƈ且没有共享列的OLTPpȝ来说是个不错的选择。当然你不得不牺牲超cM其他cM间的兌?/li><li>采用混合{略Q例?#8220;每个cdơ一张表”中嵌?#8220;每个子类一张表”Q这样可以利用不同策略的优势。随着你项目的q化Q如果你要反复重新映,那你可能也会采用该策略?/li><li>“使用隐式多态实现每个具体类一张表”q种做法q不推荐Q因为其配置q于J缛、?#8220;any”元素的复杂关联语法和隐式查询的潜在危险性?</li></ul> <blockquote> <p><strong>范例4</strong></p> <p>下面是一个交易描q应用程序的部分领域cdQ?/p> <p><img style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" alt="" src="http://www.infoq.com/resource/articles/hibernate_tuning/zh/resources/image2.jpg" _href="img://image2.jpg" _p="true" /></p> <p>开始时Q项目只有GasDeal和少数用P它?#8220;每个cdơ一张表”?/p> <p>OilDeal和ElectricityDeal是后期生更多业务需求后加入的。没有改变映策略。但是ElectricityDeal有太多自q属性,因此有很多电相关的可I字D加入了Deal表。因为用户量也在增长Q数据修改变得越来越慢?/p> <p>重新设计时我们用了两张单独的表Q分别针Ҏ/油和늛关的属性。新的映؜合了“每个cdơ一张表”?#8220;每个子类一张表”。我们还重新设计了查询,以便允许针对具体交易子类q行选择Q消除不必要的列和表q接?/p></blockquote> <h3>4.3 领域对象调优</h3> <p>Z<strong>4.1</strong><strong>?/strong>中对业务规则和设计的调优Q你得到了一个用POJO来表C的领域对象的类图。我们徏议:</p> <h4>4.3.1 POJO调优</h4> <ul><li>从读写数据中类似引用这L只读数据和以Mؓȝ数据分离出来?br />只读数据的二U缓存是最有效的,其次是以Mؓȝ数据的非严格d。将只读POJO标识Z可更改的QimmutableQ也是一个调优点。如果一个服务层Ҏ只处理只L据,可以它的事务标为只读,q是优化Hibernate和底层JDBC驱动的一个方法?/li><li>l粒度的POJO和粗_度的数据表?br />Z数据的修改ƈ发量和频率等内容来分解大的POJO。尽你可以定义一个粒度非常细的对象模型,但粒度过l的表会D大量表连接,q对数据仓库来说是不能接受的?/li><li>优先使用非final的类?br />Hibernate只会针对非final的类使用CGLIB代理来实现g时关联获取。如果被兌的类是final的,Hibernate会一ơ加载所有内容,q对性能会有影响?/li><li>使用业务键ؓ分离QdetachedQ实例实现equals()和hashCode()Ҏ?br />在多层系l中Q经常可以在分离对象上用乐观锁来提升系lƈ发性,辑ֈ更高的性能?/li><li>定义一个版本或旉戛_性?br />乐观锁需要这个字D|实现长对话(应用E序事务Q[译注Qsession译ؓ会话Qconversion译ؓ对话Q以C区别]?/li><li>优先使用l合POJO?br />你的前端UIl常需要来自多个不同POJO的数据。你应该向UI传递一个组合POJO而不是独立的POJO以获得更好的|络性能?br />有两U方式在服务层构建组合POJO。一U是在开始时?.2载所有需要的独立POJOQ随后抽取需要的属性放入组合POJOQ另一U是使用HQL投媄Q直接从数据库中选择需要的属性?br />如果其他地方也要查找q些独立POJOQ可以把它们放进二~存以便׃nQ这时第一U方式更好;其他情况下第二种方式更好?</li></ul> <h4>4.3.2 POJO之间兌的调?/h4> <ul><li>如果可以用one-to-one、one-to-many或many-to-one的关联,׃要用many-to-many?/li><li>many-to-many兌需要额外的映射表?br />管你的Java代码只需要处理两端的POJOQ但查询Ӟ数据库需要额外地兌映射表,修改旉要额外的删除和插入?/li><li>单向兌优先于双向关联?br />׃many-to-many的特性,在双向关联的一端加载对象会触发另一端的加蝲Q这会进一步触发原始端加蝲更多的数据,{等?br />one-to-many和many-to-one的双向关联也是类似的Q?a><u><font color="#0b59b2">当你从多端(子实体)定位C端(父实体)</font></u></a>?br />q样的来回加载很耗时Q而且可能也不是你所期望的?/li><li>不要Z兌而定义关联;只在你需要一起加载它们时才这么做Q这应该׃的业务规则和设计来决定(?strong>范例</strong><strong>5</strong>Q?br />另外Q你要么不定义Q何关联,要么在子POJO中定义一个值类型的属性来表示父POJO的IDQ另一个方向也是类似的Q?/li><li>集合调优<br />如果集合排序逻辑能由底层数据库实玎ͼ׃?#8220;order-by”属性来代替“sort”Q因为通常数据库在q方面做得比你好?br />集合可以是值类型的Q元素或l合元素Q,也可以是实体引用cd的(one-to-many或many-to-many兌Q。对引用cd集合的调优主要是调优获取{略。对于值类型集合的调优QHRD <sup>[1]</sup>中的<u>20.5</u><u>?#8220;理解集合性能”</u>已经做了很好的阐q?/li><li>获取{略调优。请?strong>4.7</strong><strong>节的范例</strong><strong>5</strong>?</li></ul> <blockquote> <p><strong>范例5</strong></p> <p>我们有一个名为ElectricityDeals的核心POJO用于描述늚交易。从业务角度来看Q它有很多many-to-one兌Q例如和Portfolio、Strategy和Trader{的兌。因为引用数据十分稳定,它们被缓存在前端Q能Z其ID属性快速定位到它们?/p> <p>Z有好的加载性能QElectricityDeal只映元数据Q即那些引用POJO的值类型ID属性,因ؓ在需要时Q可以在前端通过portfolioKey从缓存中快速查找PortfolioQ?/p><pre><font color="#0080ff"><property</font> <font color="#800000">name</font>=<em>"<font color="#0000ff">portfolioKey</font>"</em> <font color="#800000">column</font>=<font color="#0000ff"><em>"PORTFOLIO_ID" </em><font color="#800000">type</font>=<em>"</em>integer<em>"</em>/></font> </pre> <p>q种隐式兌避免了数据库表连接和额外的字D选择Q降低了数据传输的大?/p></blockquote> <h3>4.4 q接池调?/h3> <p>׃创徏物理数据库连接非常耗时Q你应该始终使用q接池,而且应该始终使用生U连接池而非Hibernate内置的基本连接池法?/p> <p>通常会ؓHibernate提供一个有q接池功能的数据源。Apache DBCP的BasicDataSource<sup>[13]</sup>是一个流行的开源生产数据源。大多数数据库厂商也实现了自q兼容JDBC 3.0的连接池。D例来_你也可以使用Oracle ReaApplication Cluster <sup>[15]</sup>提供的JDBCq接?sup>[14]</sup>以获得连接的负蝲均衡和失败{UR?/p> <p>不用多说Q你在网上能扑ֈ很多关于q接池调优的技术,因此我们只讨论那些大多数q接池所共有的通用调优参数Q?/p> <ul><li>最池大小Q连接池中可保持的最连接数?/li><li>最大池大小Q连接池中可以分配的最大连接数?br />如果应用E序有高q发Q而最大池大小又太,q接池就会经常等待。相反,如果最池大小太大Q又会分配不需要的q接?/li><li>最大空闲时_q接池中的连接被物理关闭前能保持I闲的最大时间?/li><li>最大等待时_q接池等待连接返回的最大时间。该参数可以预防失控事务Qrunaway transactionQ?/li><li>验证查询Q在连接返回给调用方前用于验证q接的SQL查询。这是因Z些数据库被配|ؓ会杀掉长旉I闲的连接,|络或数据库相关的异怹可能会杀死连接。ؓ了减此cd销Q连接池在空闲时会运行该验证?</li></ul> <h3>4.5事务和ƈ发的调优</h3> <p>短数据库事务对Q何高性能、高可扩展性的应用E序来说都是必不可少的。你使用表示对话h的会话来处理单个工作单元Q以此来处理事务?/p> <p>考虑到工作单元的范围和事务边界的划分Q有3中模式:</p> <ul><li><strong>每次操作一个会话?/strong>每次数据库调用需要一个新会话和事务。因为真实的业务事务通常包含多个此类操作和大量小事务Q这一般会引v更多数据库活动(主要是数据库每次提交需要将变更h到磁盘上Q,影响应用E序性能。这是一U反模式Q不该用它?/li><li><strong>使用分离对象Q每ơ请求一个会话?/strong>每次客户端请求有一个新会话和一个事务,使用Hibernate?#8220;当前会话”Ҏ将两者关联v来?br />在一个多层系l中Q用户通常会发起长对话Q或应用E序事务Q。大多数旉我们使用Hibernate的自动版本和分离对象来实C观ƈ发控制和高性能?/li><li><strong>带扩展(或长Q会话的每次对话一会话?/strong>在一个也怼跨多个事务的长对话中保持会话开启。尽这能把你从重新兌中解脱出来,但会话可能会内存溢出Q在高ƈ发系l中可能会有旧数据?</li></ul> <p>你还应该注意以下几点?nbsp;</p> <ul><li>如果不需要JTAq本地事务Q因为JTA需要更多资源,比本C务更慢。就你有多个数据源Q除非有跨多个数据库的事务,否则也不需要JTA。在最后的一个场景下Q可以考虑在每个数据源中用本C务,使用一U类?#8220;Last Resource Commit Optimization”<sup>[16]</sup>的技术(见下面的<strong>范例</strong><strong>6</strong>Q?/li><li>如果不涉及数据变_事务标Cؓ只读的,像<strong>4.3.1</strong><strong>?/strong>提到的那栗?/li><li>L讄默认事务时。保证在没有响应q回l用hQ没有行Z当的事务会完全占有资源。这ҎC务也同样有效?/li><li>如果Hibernate不是独占数据库用P乐观锁会失效Q除非创建数据库触发器ؓ其他应用E序对相同数据的变更增加版本字段倹{?</li></ul> <blockquote> <p><strong>范例6</strong></p> <p>我们的应用程序有多个在大多数情况下只和数据库“A”打交道的服务层方法;它们偶尔也会从数据库“B”中获取只L据。因为数据库“B”只提供只L据,我们对这些方法在q两个数据库上仍然用本C务?/p> <p>服务层上有一个方法设计在两个数据库上执行数据变更。以下是伪代码:</p><pre><font color="#008000">//Make sure a local transaction on database A exists</font> @Transactional (readOnly=<strong><font color="#800000">false</font></strong>, propagation=Propagation.<em><font color="#0000ff">REQUIRED</font></em>) <font color="#800000"><strong>public</strong> <strong>void</strong></font> saveIsoBids() { <font color="#008000"> //it participates in the above annotated local transaction</font> insertBidsInDatabaseA(); <font color="#008000"> //it runs in its own local transaction on database B </font> insertBidRequestsInDatabaseB(); <font color="#008000">//must be the last operation </font></pre> <p>因ؓ<strong>insertBidRequestsInDatabaseB()</strong>是saveIsoBids ()中的最后一个方法,所以只有下面的场景会造成数据不一_</p> <p>在saveIsoBids()执行q回Ӟ数据?#8220;A”的本C务提交失败?/p> <p>但是Q就saveIsoBids()使用JTAQ在两阶D|交(2PCQ的W二个提交阶D失败的时候,你还是会到数据不一致。因此如果你能处理好上述的数据不一致性,而且不想Z一个或数几个Ҏ引入JTA的复杂性,你应该用本C务?/p></blockquote> <p>Q未完待l)</p> <img src ="http://www.aygfsteel.com/zstop/aggbug/352567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.aygfsteel.com/zstop/" target="_blank">...</a> 2011-06-18 11:59 <a href="http://www.aygfsteel.com/zstop/archive/2011/06/18/352567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]Spring3.05单集成MyBatis3.03http://www.aygfsteel.com/zstop/archive/2011/06/18/352565.html......Sat, 18 Jun 2011 03:42:00 GMThttp://www.aygfsteel.com/zstop/archive/2011/06/18/352565.htmlhttp://www.aygfsteel.com/zstop/comments/352565.htmlhttp://www.aygfsteel.com/zstop/archive/2011/06/18/352565.html#Feedback0http://www.aygfsteel.com/zstop/comments/commentRss/352565.htmlhttp://www.aygfsteel.com/zstop/services/trackbacks/352565.html阅读全文

... 2011-06-18 11:42 发表评论
]]>
վ֩ģ壺 Դ| Ϫ| ƽ| DZɽ| ϲ| | | | | ɽ| ƽ| ʯȪ| | | | | ӳ| | Զ| | Ԫ| »| Ƹ| ׿| ˫| | üɽ| | ͨ| ƽ| ָɽ| ³| ׷| ѭ| ӽ| ƾ| ̨| | | | |