首页 > 代码库 > 性能优化(1+N,list与iterator,缓存,事务)

性能优化(1+N,list与iterator,缓存,事务)

1、注意session.clear()的运用,尤其是不断分页循环的时候

  A 在一个大集合中进行遍历,取出其中含有敏感字的对象

  B 另一种形式的内存泄露.

2、1+N问题

问题描述:如@ManyToOne时,两个类分别是User与Group,取User时,本想发一条SQL语句,结果顺带发了N条语句,将每个User对应的Group也查询了。

解决方法有三种:

  (1)设为@ManyToOne(fetch=FetchType.LAZY)

  (2)在Group类中的@Entity下面加一条@BatchSize(size=5),则每一条SQL语句可以取出5个Group对象

  (3)查询语句写为“from User u left join fetch u.group g”

3、list和iterator的区别

  (1)list()返回List,直接取对象;list第二次发出,仍会到数据库中查询数据

  (2)iterator先取对象的主键,即ID,等到要用的时候再根据ID取出对象;iterator第二次首先查找session级缓存.

4、缓存

(1)一级缓存(session级别的缓存)

  例如,同一个session中,load两次,只向数据库发一条SQL语句。但如果是两个不同session中,分别load一次,则发两条SQL语句。

(2)二级缓存(SessionFactory级别的缓存,可以跨越session级别存在)

  两个不同session中,分别load一次,要想只发一条SQL语句,则需要利用二级缓存。

  load默认使用二级缓存,iterator默认使用二级缓存

  list默认向二级缓存添加数据,但是查询的时候不使用.

  如果Query需要使用二级缓存,则打开查询缓存。

  适用情况:经常被访问,改动不大,数量有限的情况,如用户权限,组织机构等。

  使用方法:Hibernate不提供二级缓存的实现,由其他厂商提供(如EH,OS,Swarm,JBoss)。使用时要配置xml,导入jar包。

       在相关类中需要@Entity@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

(3)查询缓存:在二级缓存设置有效时才可以使用,需要在xml中设置。相同的查询语句才能使用查询缓存。 

  需要调用Query setCachable(true)方法指明使用二级缓存.

5、缓存算法

LRU,LFU, FIFO

Least Recently Used 按时间

Least Frequently Userd 按命中次数

First In First Out

memoryStoreEvictionPlicy=”LRU”(ehcache)

6、事务并发

(1)ACID 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

(2)事物并发带来的问题:

  • 脏读:读了其他未提交事务B的数据,该事务B后来被回滚了
  • 不可重复读:同一事务中,读了两遍,前后数据不一致。因为其他事务B更改了数据
  • 幻读:同一事务中,读了两遍,前后数据不一致。因为其他事务B插入/删除了数据

 

(3)数据库事务隔离级别:(javax.sql.Connection)

  • READ_UNCOMMITTED:允许读取改变了的还未提交的数据,可能导致脏读、不可重复读和幻读。 
  • READ COMMITTED(Oracle默认):允许并发事务提交之后读取,可以避免脏读,可能导致重复读和幻读。 
  • REPEATABLE_READ(MySQL默认):对相同字段的多次读取结果一致,可导致幻读。 
  • SERIALIZABLE:完全服从ACID的原则,确保不发生脏读、不可重复读和幻读。 

                                  Dirty reads          non-repeatable reads            phantom reads 
Serializable                        不会                        不会                                  不会 
REPEATABLE READ             不会                        不会                                  会 
READ COMMITTED              不会                          会                                   会 
Read Uncommitted              会                            会                                    会 

(4)一般选择READ COMMITTED,在此前提下,解决不可重复读问题(忽略幻读)有两种方式

  • 悲观锁:依赖于数据库。session.load(**.class,1,LockMode.UPGRADE);相当于select...from...where...for update
  • 乐观锁:与数据库无关,效率高。在类中加入private int version;属性@Version 该属性由Hibernate控制,没更新一次加1,不一致时报错。