Hibernate性能优化技巧

在进行Hibernate性能优化时,须要从如下几个方面进行考虑:sql

数据库设计调整。数据库

HQL优化。缓存

API的正确使用(如根据不一样的业务类型选用不一样的集合及查询API)。性能优化

主配置参数(日志、查询缓存、fetch_size、batch_size等)。session

映射文件优化(ID生成策略、二级缓存、延迟加载、关联优化)。并发

一级缓存的管理。数据库设计

针对二级缓存,还有许多特有的策略。性能

事务控制策略。fetch

数据的查询性能每每是影响一个应用系统性能的主要因素。对查询性能的影响会涉及到系统软件开发的各个阶段,例如,良好的设计、正确的查询方法、适当的缓存都有利于系统性能的提高。大数据

系统性能的提高设计到系统中的各个方面,是一个相互平衡的过程,须要在应用的各个阶段都要考虑。而且在开发、运行的过程当中要不断地调整和优化才能逐步提高系统的性能。

设计阶段的考虑问题

一个良好的数据库结构有利于系统性能的提高。这里所说的良好结构的数据库并不单纯是指知足数据库设计范式的数据库结构。这是由于,按照数据库范式所设计的数据库只能说在结构上是最优的,没有冗余数据等问题,但在生产过程当中并不必定能得到最佳的性能。有时候适当地增长一些数据的冗余虽然增长了数据维护的难度,但能够极大地简化业务的查询,提升数据检索的效率。

在使用Java访问数据库的时候,还存在另一个问题,就是面向对象的Java语言与关系型数据库之间的矛盾。在这二者之间必然要涉及到一个相互转化的问题,对于这个问题是否可以正确的处理也是影响系统性能的一个重要因素。

综合以上提出的各类问题,在数据库设计阶段要综合考虑如下三个方面的因素。

Java建模

在创建Java对象模型的时候,要考虑数据库持久化的方便性,所创建的Java对象模型应该能够很容易地被数据所存储,而且数据库中表的结构也是越简单越好。

数据库结构

在设计数据库结构的时候也要考虑到是否能够很容易地用Java对象去表示。这里并非简单的一个表对应一个对象的直接转换,更重要的是转换后的Java对象应该可以描述出数据间的关系。

因此在设计阶段,对于Java对象和数据库结构要进行综合考虑,也就是能够从两个方向进行考虑,毕竟二者之间不是一个时代的产物,设计的结果应该在二者之间达到一个平衡,虽然不能每一方都达到最优,但也不能形成有一方结构不好的状况。就像装水的木桶,最矮的板子决定水桶的容量。

业务需求

前面两个因素都是纯技术方面的考虑,在设计的过程当中,更重要的是要紧扣业务需求。这是由于任何的软件系统都是以业务为中心的,那么对于系统的设计也不例外,在设计的阶段就应该考虑业务实现的方便性以及执行的效率。一个良好的结构设计不但使业务功能的实现变得很是容易而且能够避免不少复杂的操做,还能够达到提高系统性能的目的。

设计阶段是整个应用系统开发中的根基,其对软件的影响仅次于对系统需求的把握。因此在设计阶段应该对整个软件系统有一个总体的考虑,这里所说的具体设计也只是设计阶段中的不多的一部分,综合考虑多方面的因素才能达到更佳的性能。

 

文章分为十三个小块儿对Hibernate性能优化技巧进行总结性分析,分析以下:

1、在处理大数据量时,会有大量的数据缓冲保存在Session的一级缓存中,这缓存大太时会严重显示性能,因此在使用Hibernate处理大数据量的,可使用session. clear()或者session. evict(Object) 在处理过程当中,清除所有的缓存或者清除某个对象。

2、对大数据量查询时,慎用list()或者iterator()返回查询结果,

<1>. 使用List()返回结果时,Hibernate会全部查询结果初始化为持久化对象,结果集较

大时,会占用不少的处理时间。

<2>. 而使用iterator()返回结果时,在每次调用iterator.next()返回对象并使用对象时,

Hibernate才调用查询将对应的对象初始化,对于大数据量时,每调用一次查询都会花

费较多的时间。当结果集较大,可是含有较大量相同的数据,或者结果集不是所有都会

使用时,使用iterator()才有优点。

<3>. 对于大数据量,使用qry.scroll()能够获得较好的处理速度以及性能。并且直接对结

果集向前向后滚动。

3、对于关联操做,Hibernate虽然能够表达复杂的数据关系,但请慎用,使数据关系较为

简单时会获得较好的效率,特别是较深层次的关联时,性能会不好。

4、对含有关联的PO(持久化对象)时,若default-cascade="all"或者 “save-update”,新增PO时,请注意对PO中的集合的赋值操做,由于有可能使得多执行一次update操做。

5、在一对多、多对一的关系中,使用延迟加载机制,会使很多的对象在使用时才会初始化,这样可以使得节省内存空间以及减小数据库的负荷,并且若PO中的集合没有被使用时,就可减小互数据库的交互从而减小处理时间。

6、对于大数据量新增、修改、删除操做或者是对大数据量的查询,与数据库的交互次数是决定处理时间的最重要因素,减小交互的次数是提高效率的最好途径,因此在开发过程当中,请将show_sql设置为true,深刻了解Hibernate的处理过程,尝试不一样的方式,可使得效率提高。

7、Hibernate是以JDBC为基础,可是Hibernate是对JDBC的优化,其中使用Hibernate的缓冲机制会使性能提高,如使用二级缓存以及查询缓存,若命中率较高明,性能会是到大幅提高。

8、Hibernate能够经过设置hibernate.jdbc.fetch_size,hibernate.jdbc.batch_size等属性,对Hibernate进行优化。

9、不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳,大量并发insert数据时可能会引发表之间的互锁。数据库提供的主键生成机制,每每是经过在一个内部表中保存当前主键状态(如对于自增型主键而言,此内部表中就维护着当前的最大值和递增量),以后每次插入数据会读取这个最大值,而后加上递增量做为新记录的主键,以后再把这个新的最大值更新回内部表中,这样,一次Insert操做可能致使数据库内部屡次表读写操做,同时伴随的还有数据的加锁解锁操做,这对性能产生了较大影响。所以,对于并发Insert要求较高的系统,推荐采用uuid.hex 做为主键生成机制。

10、Dynamic Update 若是选定,则生成Update SQL 时不包含未发生变更的字段属性,这样能够在必定程度上提高SQL执行效能.Dynamic Insert 若是选定,则生成Insert SQL 时不包含未发生变更的字段属性,这样能够在必定程度上提高SQL执行效能

11、在编写代码的时候请,对将POJO的getter/setter方法设定为public,若是设定为private,Hibernate将没法对属性的存取进行优化,只能转而采用传统的反射机制进行操做,这将致使大量的性能开销(特别是在1.4以前的Sun JDK版本以及IBM JDK中,反射所带来的系统开销至关可观)。

12、在one-to-many 关系中,将many 一方设为主动方(inverse=false)将有助性能的改善。

十3、因为多对多关联的性能不佳(因为引入了中间表,一次读取操做须要反复数次查询),所以在设计中应该避免大量使用。

还能够看看Struts与Hibernate的完美结合方案