1、查询缓存
首先需要配置hibernate.cache.use_query_cache=true
如果用ehcache,配置ehcache.xml,注意hibernate3.0以后不是net.sf的包名了
1
<
cache
name
="net.sf.hibernate.cache.StandardQueryCache"
2
3
maxElementsInMemory
="50"
eternal
="false"
timeToIdleSeconds
="3600"
4
5
timeToLiveSeconds
="7200"
overflowToDisk
="true"
/>
6
7
<
cache
name
="net.sf.hibernate.cache.UpdateTimestampsCache"
8
9
maxElementsInMemory
="5000"
eternal
="true"
overflowToDisk
="true"
/>
10
11
然后
query.setCacheable(true);//激活查询缓存
query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion,可选
第二行指定要使用的cacheRegion是myCacheRegion,即你可以给每个查询缓存做一个单独的配置,
使用setCacheRegion来做这个指定,需要在ehcache.xml里面配置它:
1
<
cache
name
="myCacheRegion"
maxElementsInMemory
="10"
eternal
="false"
2
3
timeToIdleSeconds
="3600"
timeToLiveSeconds
="7200"
overflowToDisk
="true"
/>
4
5
如果省略第二行,不设置cacheRegion的话,那么会使用上面提到的标准查询缓存的配置,也就是
net.sf.hibernate.cache.StandardQueryCache
问题:当hibernate更新数据库的时候,它怎么知道更新哪些查询缓存呢?
hibernate在一个地方维护每个表的最后更新时间,其实也就是放在上面
net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。
当通过hibernate更新的时候,hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时间和这个缓存所查询的表,当hibernate查询一个缓存是否存在的时候,如果缓存存在,它还要取出缓存的生成时间和这个缓存所查询的表,然后去查找这些表的最后更新时间,如果有一个表在生成时间后更新过了,那么这个缓存是无效的。可以看出,只要更新过一个表,那么凡是涉及到这个表的查询缓存就失效了,因此查询缓存的命中率可能会比较低。
注意:
放入缓存中的key是查询的语句,value是查询之后得到的结果集的id列表。
表面看来这样的方案似乎能解决hql利用缓存的问题,但是需要注意的是,构成key的是:
hql生成的sql、sql的参数、排序、分页信息等。也就是说如果你的hql有小小的差异,
比如第一条hql取1-50条数据,第二条hql取20-60条数据,那么hibernate会认为这是两个
完全不同的key,无法重复利用缓存。因此利用率也不高。
查询缓存必须配合二级缓存一起使用,否则极易出现1+N的情况
如果不设置"查询缓存",那么hibernate只会缓存使用load()方法获得的单个持久化对象,
如果想缓存使用findall()、list()、Iterator()、createCriteria()、createQuery()等方法
获得的数据结果集的话,就需要设置hibernate.cache.use_query_cache true才行,如果需要"查询缓存",需要在使用Query或Criteria()时设置其setCacheable(true);属性。
2、Collection缓存
需要在hbm的collection里面设置
<
cache
usage
="read-write"
/>
假如class是Cat,collection叫children,那么ehcache里面配置
1
<
cache
name
="com.xxx.pojo.Cat.children"
2
3
maxElementsInMemory
="20"
eternal
="false"
timeToIdleSeconds
="3600"
4
5
timeToLiveSeconds
="7200"
6
7
overflowToDisk
="true"
/>
8
Collection的缓存和前面查询缓存的list一样,也是只保持一串id,但它不会因为这个表更新过就
失效,一个collection缓存仅在这个collection里面的元素有增删时才失效。
这样有一个问题,如果你的collection是根据某个字段排序的,当其中一个元素更新了该字段时,
导致顺序改变时,collection缓存里面的顺序没有做更新
3、Class缓存(也称二级缓存)
可由Hibernate提供的二级缓存实现,它存在于SessionFactory级别,
缓存结构可以看作是一个hash table,key是数据库记录的id,value是id对应的pojo对象。
当用户根据id查询对象的时候(load、iterator方法),会首先在缓存中查找,
如果没有找到再发起数据库查询。但是如果使用hql发起查询(find, query方法)
则不会利用二级缓存,而是直接从数据库获得数据,但是它会把得到的数据放到二级缓存备用。也就是说,基于hql的查询,对二级缓存是只写不读的。
在hibernate.cfg.xml配置:
<
property
name
="hibernate.cache.provider_class"
>
org.hibernate.cache.EhCacheProvider
</
property
>
hibernate3支持
Hashtable Cache(org.hibernate.cache.HashtableCacheProvider)
EhCache(org.hibernate.cache.EhCacheProvider)
OSCache(org.hibernate.cache.OSCacheProvider)
SwarmCache(org.hibernate.cache.SwarmCacheProvider)
JBossCache(org.hibernate.cache.TreeCacheProvider)
在相应的POJO配置文件中增加:
<!--
指定缓存同步策略:
read-write 读写型
nonstrict-read-write 非严格读写型
read-only 只读型
transactional 事务型
-->
<cache usage="read-write"/>
Cache
read-only
nonstrict-read-write
read-write
transactional
EhCache |
Yes |
Yes |
Yes |
No |
OSCache |
Yes |
Yes |
Yes |
No |
SwarmCache |
Yes |
Yes |
No |
No |
TreeCache |
Yes |
No |
No |
Yes |
对于一条记录,也就是一个PO来说,是根据ID来找的,缓存的key就是ID,value是POJO。无论
list,load还是iterate,只要读出一个对象,都会填充缓存。但是list不会使用缓存,而iterate
会先取数据库select id出来,然后一个id一个id的load,如果在缓存里面有,就从缓存取,没有
的话就去数据库load。
当某个ID通过hibernate修改时,hibernate会知道,于是移除缓存。
这样大家可能会想,同样的查询条件,第一次先list,第二次再iterate,就可以使用到缓存了。
实际上这是很难的,因为你无法判断什么时候是第一次,而且每次查询的条件通常是不一样的,假
如数据库里面有100条记录,id从1到100,第一次list的时候出了前50个id,第二次iterate的时候
却查询到30至70号id,那么30-50是从缓存里面取的,51到70是从数据库取的,共发送1+20条sql。
所以我一直认为iterate没有什么用,总是会有1+N的问题。 如果想要对list或者iterate查询的结
果缓存,就要用到查询缓存了。
注意:
对于one-to-many的关联关系,如果对one应用缓存,则应同时对many应用。
二级缓存的失效机制由hibernate控制,当某条数据被修改之后,hibernate会根据它的id去做
缓存失效操作。基于此机制,如果数据表不是被hibernate独占,那么二级缓存无法得到有效控制
。
hibernate 3.0在做批量修改、批量更新的时候,是不会同步更新二级缓存的
查询缓存和二级缓存是有关联关系的,他们不是完全独立的两套东西。假如一个查询条件hql_1
,第一次被执行的时候,它会从数据库取得数据,然后把查询条件作为key,把返回数据的所有id
列表作为value(请注意仅仅是id)放到查询缓存中,同时整个结果集放到二级缓存,key是id,
value是pojo对象。当你再次执行hql_1,它会从缓存中得到id列表,然后根据这些列表一个一个的
到二级缓存里面去找pojo对象,如果找不到就向数据库发起查询。也就是说,如果二级缓存配置了
超时时间,就有可能出现查询缓存命中了,获得了id列表,但是class里面相应的pojo已经因为超
时被失效,hibernate就会根据id清单,一个一个的去向数据库查询,有多少个id,就执行多少个
sql。该情况将导致性能下降严重。
查询缓存的失效机制也由hibernate控制,数据进入缓存时会有一个timestamp,它和数据表的
timestamp对应。当hibernate环境内发生save、update等操作时,会更新被操作数据表的
timestamp。用户在获取缓存的时候,一旦命中就会检查它的timestamp是否和数据表的timestamp
匹配,如果不,缓存会被失效。因此查询缓存的失效控制是以数据表为粒度的,只要数据表中任何
一条记录发生一点修改,整个表相关的所有查询缓存就都无效了。因此查询缓存的命中率可能会很
低。
4、对方法的缓存
对于调用频率较高的查询类方法,我们希望缓存方法结果
在spring中可利用拦截器(Interceptor)实现,可能如下面的配置:
1
<
beans
>
2
3
<
bean
id
="cacheInterceptor"
4
5
class
="org.springframework.aop.interceptor.cache.OSCacheInterceptor"
>
6
7
<!
- 默认刷新时间(秒)-
>
8
9
<
property
name
="defaultRefreshPeriod"
>
10
11
<
value
>
60
</
value
>
12
13
</
property
>
14
15
<
property
name
="identifiers"
>
16
17
<
props
>
18
19
<
prop
key
="java.util.Map"
>
toString
</
prop
>
20
21
</
props
>
22
23
</
property
>
24
25
</
bean
>
26
27
<!
- 正则表达式匹配 -
>
28
29
<
bean
id
="searcherAdvisor"
30
31
class
="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
>
32
33
<
property
name
="advice"
>
34
35
<
ref
local
="cacheInterceptor"
/>
36
37
</
property
>
38
39
<
property
name
="patterns"
>
40
41
<
list
>
42
43
<
value
>
.get.
</
value
>
44
45
</
list
>
46
47
</
property
>
48
49
</
bean
>
50
51
<!
- 自动代理 -
>
52
53
<
bean
id
="proxyCreator1"
54
55
class
="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
>
56
57
<
property
name
="beanNames"
>
58
59
<!--
需截获方法的bean列表
-->
60
61
<
list
>
62
63
<
value
>
commonSelect
</
value
>
64
65
</
list
>
66
67
</
property
>
68
69
<
property
name
="interceptorNames"
>
70
71
<!--
截获器列表
-->
72
73
<
list
>
74
75
<
value
>
searcherAdvisor
</
value
>
76
77
</
list
>
78
79
</
property
>
80
81
</
bean
>
82
83
<
beans
>
84
85
这里通过自动代理创建bean,并指定作用其上的interceptor列表,在commonSelect存在searchAdvisor,
而searchAdvisor对匹配*get*模式的方法调用将通过cacheInterceptor进行处理。
分享到:
相关推荐
用C语言实现简单的测试单击cache的小程序; 利用大循环 读写cache 运行时间较长。
当多个Cache层次同时保存有同一数据时,若其中一个Cache层次中的数据被修改了,其他层次上的数据必须相应更新,以保证数据的一致性。一致性则是关于如何维护处理器之间或多个线程之间对共享数据访问的一致性。为了...
在多级Cache层次结构中,L1 Cache通常是最靠近处理器的高速缓存,具有最小的延迟和最高的访问速度。L2 Cache容量较大,访问速度略低,但仍优于L1 Cache。对于现代高性能处理器,可能还会存在L3 Cache甚至更高层级的...
#### Cache层次与操作 MIPS处理器支持不同层级的Cache,包括一级指令Cache(I)、一级数据Cache(D)、二级Cache(S)和三级Cache(T)。每种Cache类型都有其特定的操作,如索引作废、索引加载Tag、索引存储Tag、...
2. Cache 层次结构(1980s-1990s):随着 Cache 技术的发展,Cache 层次结构的概念被提出。这期间, Cache 技术的主要发展方向是优化 Cache 的层次结构,以提高 Cache 的性能。 3. Cache 优化技术(1990s-2000s):...
- CPU通常包含多个不同大小和速度的Cache层级,如L1、L2和L3,越接近CPU的Cache层次越小但速度更快。 - 每个Cache层级都有特定的用途和设计考量,以达到最优的数据访问速度和系统效率。 6. 数据预读策略: - ...
6. Cache层次结构 现代处理器内部可能包含多层Cache结构,如ARM处理器的多级缓存系统,这种层次结构的设计可以进一步减少访问延迟并提高吞吐量。上层Cache(如L1)比下层(如L2或L3)拥有更低的延迟但容量较小,下层...
1. **Cache层次结构**:现代处理器通常有多个级别的缓存,如L1、L2和L3,它们具有不同的容量、速度和访问延迟。模拟器应能够处理不同级别的缓存特性。 2. **替换策略**:当Cache满时,需要决定哪些数据应该被替换...
传统上,研究者通过调整Cache参数、 Cache层次结构和组织、 Cache控制策略等来优化Cache性能。但是,这些方法都存在一定的缺陷,例如, Cache参数的调整可能会增加系统的面积、时钟延迟和功耗,而编译技术优化Cache...
- **Cache层次结构**:现代计算机系统通常配备多级Cache,如L1、L2甚至L3 Cache。每级Cache的容量、速度及成本各不相同。 #### Cache的主要参数 - **容量**:Cache能够存储的数据总量。 - **块大小**:Cache中每个...
2. **hybris Cache层次**:hybris Commerce有多种缓存层次,包括本地缓存(Local Cache)、二级缓存(Second Level Cache)和分布式缓存(Distributed Cache)。本地缓存存在于每个服务器实例中,而二级缓存和分布式...
在IT领域,尤其是在计算机系统架构中,理解和模拟Cache与主存、虚拟存储器的工作机制是至关重要的。这个实验旨在帮助我们深入理解存储层次结构及其优化技术。以下将详细阐述相关知识点: 1. **Cache**: Cache是...
Cache层次的作用是加速CPU访存速度,减少CPU访存时间。主存层次的作用是提供大容量的存储空间,满足程序员的需求。辅存层次的作用是扩展主存的容量,提供更大的存储空间。 3. 存储器的层次结构的管理 计算机系统中...
在ARM架构参考手册ARM V9中, readers可以了解ARM V9架构的基本概念、指令集、寄存器架构、内存管理单元(MMU)和 cache 层次结构等。同时,该手册还提供了ARM V9架构的实现细节、性能优化技术和故障排除方法等。 ...
1.Cache—主存:映像方式要实现全相联、直接映象、组相联方式三种方式,并选择每一种映像方式下输出结果;替换算法一般使用LRU算法。 3.要求主存容量、Cache大小、块大小以及组数等可以输入修改。 4.求出命中率;...
总的来说,Oracle Buffer Cache是数据库管理系统为了优化磁盘I/O而设立的一种内存机制,而Cache是一个更通用的术语,涉及到从硬件到软件的各个层次的性能优化。理解这两者的差异,对于数据库管理员和系统管理员优化...
此外,现代处理器内部的Cache层次结构也越来越复杂,了解和利用这些硬件特性也是提高程序性能的关键。 总的来说,分块技术是计算机体系结构中用于提高Cache命中率和程序性能的一种重要技术。通过理解分块技术的工作...
5. **多级Cache**:现代处理器往往采用多级Cache结构,如L1、L2和L3 Cache,以提供不同层次的缓存性能。全相联Cache可以用于其中的任一级,但通常在L1 Cache中更常见,因为其灵活性对于提高局部性好的程序性能非常...