`
benx
  • 浏览: 276330 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Hibernate 二级缓存 和 查询缓存 (转)

    博客分类:
  • java
阅读更多

Hibernate 二级缓存 查询缓存

 

二级缓存和查询缓存都相当于一个map

二级缓存缓存的keyidvalue为实体对象。一般loadget ,iterate使用到二级缓存,list()需要结合查询缓存使用。

iteratelist区别如下:

iterate不需要开启查询缓存,它首先发出一个sql如”select s.id from Student s”去数据库把id属性列表取出来,然后再根据id列表一个一个load(),如果缓存有从缓存取,如果缓存没有就从数据库取:select s.id,s.name,s.classid from     Student s where s.id=?,取出后再存入二级缓存。Iterate总会发出取id列表的语句。

 

List需要开启查询缓存,它首先发出一个sql如”select s.id,s.name,s.classid from Student s…”去数据库取出所有相关实体,并将这些实体存入二级缓存,将此sql语句及一些相关信息作为keyid列表作为值,第二次查询这条语句时就会去根据sql语句及相关信息去key里找,如果有就会把id列表取出一个一个load(),接下来就和iterate一样了。List一般只有第一次发发出取实体列表的语句,以后的id列表就会去查询缓存取id列表,不会再发出sql语句。

 

前提:执行同一hql语句,如:select s from Student s

1.关闭查询缓存,开启二级缓存时:

第二次查询属性时iterate只会发出获取id列表的sqllist会发出和第一次一样的请求实体的sql

2.开启查询缓存,开启二级缓存

第二次查询属性时iterate只会发出获取id列表的sqllist不发sql

以上说明iterate只和二级缓存有关,list和二级缓存和查询缓存都有关。

 

 

list 不会使用二级缓存,但是会填充二级缓存,还会使用查询缓存

 

                                                    out join          使用查询缓存二级缓存

 

1.Criteria.list                                                       

2.Query.list                                    不会                   

3.Query.iterate                                                   

4.ACriteria.list                            

   BQuery.list                               不会               不会使用A的结果缓存

5.AQuery.list                               不会

   BCriteria.list                                               不会使用A的结果缓存

6.AQuery.iterate                        

   BQuery.list                               不会               不会使用A的结果缓存

7.AQuery.list                               不会

   BQuery.iterate                         不会                 使用A的结果缓存

8.ACriteria.list                            

   BQuery.iterate                                                使用A的结果缓存

9.AQuery.iterate                        

   BCriteria.list                                              不会使用A的结果缓存

 

 

1.二级缓存

如果开启了二级缓存,hibernate在执行任何一次查询的之后,都会把得到的结果集放到缓存中,缓存结构可以看作是一个hash tablekey是数据库记录的idvalueid对应的pojo对象。当用户根据id查询对象的时候(loaditerator方法),会首先在缓存中查找,如果没有找到再发起数据库查询。但是如果使用hql发起查询(find, query方法)则不会利用二级缓存(如果开启查询缓存,会使用查询缓存,否则会查询数据库),而是直接从数据库获得数据,但是它会把得到的数据放到二级缓存备用。也就是说,基于hql的查询,对二级缓存是只写不读的。

 

针对二级缓存的工作原理,采用iterator取代list来提高二级缓存命中率的想法是不可行的。Iterator的工作方式是根据检索条件从数据库中选取所有目标数据的id,然后用这些id一个一个的到二级缓存里面做检索,如果找到就直接加载,找不到就向数据库做查询。因此假如iterator检索100条数据的话,最好情况是100%全部命中,最坏情况是0%命中,执行101sql把所有数据选出来。而list虽然不利用缓存,但是它只会发起1sql取得所有数据。在合理利用分页查询的情况下,list整体效率高于iterator

二级缓存的失效机制由hibernate控制,当某条数据被修改之后,hibernate会根据它的id去做缓存失效操作。基于此机制,如果数据表不是被hibernate独占(比如同时使用JDBC或者ado等),那么二级缓存无法得到有效控制。

 

由于hibernate的缓存接口很灵活,cache provider可以方便的切换,因此支持cluster环境不是大问题,通过使用swarmcachejboss cache等支持分布式的缓存方案,可以实现。但是问题在于:

1、 分布式缓存本身成本偏高(比如使用同步复制模式的jboss cache

2、 分布式环境通常对事务控制有较高要求,而目前的开源缓存方案对事务缓存(transaction cache)支持得不够好。当jta事务发生会滚,缓存的最后更新结果很难预料。这一点会带来很大的部署成本,甚至得不偿失。

结论:不应把hibernate二级缓存作为优化的主要手段,一般情况下建议不要使用

原因如下:

1、 由于hibernate批量操作的性能不如sql,而且为了兼容1.0dao类,所以项目中有保留了sql操作。哪些数据表是单纯被hibernate独占无法统计,而且随着将来业务的发展可能会有很大变数。因此不宜采用二级缓存。

2、 针对系统业务来说,基于id检索的二级缓存命中率极为有限,hql被大量采用,二级缓存对性能的提升很有限。

3 hibernate 3.0在做批量修改、批量更新的时候,是不会同步更新二级缓存的,该问题在hibernate 3.2中是否仍然存在尚不确定。

 

 

二、hibernate的查询缓存

查询缓存的实现机制与二级缓存基本一致,最大的差异在于放入缓存中的key是查询的语句value是查询之后得到的结果集的id列表。表面看来这样的方案似乎能解决hql利用缓存的问题,但是需要注意的是,构成key的是:hql生成的sqlsql的参数、排序、分页信息等。也就是说如果你的hql有小小的差异,比如第一条hql1-50条数据,第二条hql20-60条数据,那么hibernate会认为这是两个完全不同的key,无法重复利用缓存。因此利用率也不高。

总结:也就是查询缓存的hql必须一致,才可以使用

 

另外一个需要注意的问题是,查询缓存和二级缓存是有关联关系的,他们不是完全独立的两套东西。假如一个查询条件hql_1,第一次被执行的时候,它会从数据库取得数据,然后把查询条件作为key,把返回数据的所有id列表作为value(请注意仅仅是id)放到查询缓存中,同时整个结果集放到class缓存(也就是二级缓存),keyidvaluepojo对象。当你再次执行hql_1,它会从缓存中得到id列表,然后根据这些列表一个一个的到class缓存里面去找pojo对象,如果找不到就向数据库发起查询。也就是说,如果二级缓存配置了超时时间(或者发呆时间),就有可能出现查询缓存命中了,获得了id列表,但是class里面相应的pojo已经因为超时(或发呆)被失效,hibernate就会根据id清单,一个一个的去向数据库查询,有多少个id,就执行多少个sql。该情况将导致性能下降严重。

总结:也就是查询缓存如果hql一样,也有可能发生N+1查询

 

查询缓存的失效机制也由hibernate控制,数据进入缓存时会有一个timestamp,它和数据表的timestamp对应。当hibernate环境内发生saveupdate等操作时,会更新被操作数据表的timestamp。用户在获取缓存的时候,一旦命中就会检查它的timestamp是否和数据表的timestamp匹配,如果不,缓存会被失效。因此查询缓存的失效控制是以数据表为粒度的,只要数据表中任何一条记录发生一点修改,整个表相关的所有查询缓存就都无效了。因此查询缓存的命中率可能会很低。

总结:查询缓存会因为表修改而失效

 

结论:不应把hibernate二级缓存作为优化的主要手段,一般情况下建议不要使用。

原因如下:

1、 项目上层业务中检索条件都比较复杂,尤其是涉及多表操作的地方。很少出现重复执行一个排序、分页、参数一致的查询,因此命中率很难提高。

2、 查询缓存必须配合二级缓存一起使用,否则极易出现1+N的情况,否则性能不升反降

3、 使用查询缓存必须在执行查询之前显示调用Query.setCacheable(true)才能激活缓存,这势必会对已有的hibernate封装类带来问题。

总结

详细分析hibernate的二级缓存和查询缓存之后,在底层使用通用缓存方案的想法基本上是不可取的。比较好的做法是在高层次中(业务逻辑层面),针对具体的业务逻辑状况手动使用数据缓存,不仅可以完全控制缓存的生命周期,还可以针对业务具体调整缓存方案提交命中率。Cluster中的缓存同步可以完全交给缓存本身的同步机制来完成。比如开源缓存swarmcache采用invalidate的机制,可以根据用户指定的策略,在需要的时候向网络中的其他swarmcache节点发送失效消息,建议采用。

 

分享到:
评论

相关推荐

    hibernate一级缓存、二级缓存和查询缓存

    **hibernate一级缓存、二级缓存和查询缓存** 在Java的持久化框架Hibernate中,缓存机制是提高应用程序性能的关键要素。缓存能够减少数据库的访问次数,提高数据读取速度,并且在一定程度上降低了系统的负载。本文将...

    hibernate一级缓存和二级缓存的区别与联系

    总结来说,Hibernate 的一级缓存和二级缓存都是为了提高数据访问效率,但它们在范围和并发控制方面有所不同。一级缓存是事务级别的,保证了数据的强一致性,而二级缓存提供了更多的灵活性,可以跨事务共享,但需要...

    Hibernate二级缓存

    Hibernate二级缓存是一种提高应用程序性能的技术,它将数据存储在SessionFactory级别的缓存中,使得数据可以在不同的Session之间共享。这与一级缓存(Session级别)不同,一级缓存仅存在于单个Session生命周期内,当...

    hibernate二级缓存实例

    在这个"hibernate二级缓存实例"中,我们将深入探讨二级缓存的原理、配置以及在实际项目中的应用。 首先,我们需要了解一级缓存和二级缓存的区别。一级缓存是Session级别的,每个Session都有自己的一级缓存,用于...

    Hibernate一级缓存、二级缓存以及查询缓存实例

    本文将深入探讨Hibernate的一级缓存、二级缓存以及查询缓存,通过具体的实例来阐述它们的工作原理和使用方法。 首先,我们从一级缓存开始。一级缓存是Hibernate默认提供的缓存,它是每个Session级别的,也被称为...

    hibernate 二级缓存详解

    在Hibernate中,二级缓存可以使用不同的提供商,例如Ehcache和OSCache。配置Ehcache作为二级缓存提供商,需要在Hibernate的配置文件中设置`hibernate.cache.provider_class`为`...

    Hibernate一级缓存和二级缓存

    **二、Hibernate二级缓存** 二级缓存是SessionFactory级别的,跨越了多个Session,可以被多个线程共享。它通常由第三方插件如EhCache、Infinispan等提供。二级缓存分为以下几种类型: 1. **集合缓存**:用于存储...

    hibernate二级缓存示例源码

    综上所述,通过学习`hibernate二级缓存示例源码`,我们可以了解到如何在实际项目中配置和使用Hibernate二级缓存,从而提升系统的性能。在实际应用中,应结合具体场景选择合适的缓存策略,以达到最佳的性能优化效果。

    hibernate开启二级缓存和查询缓存

    在 Hibernate 中,二级缓存和查询缓存是提高应用性能的重要机制。下面将详细介绍如何开启并理解这两个缓存机制。 ### 1. 一级缓存与二级缓存 #### 1.1 一级缓存 一级缓存是 Hibernate 内置的 Session 缓存,它是每...

    hibernate二级缓存包

    综上所述,Hibernate二级缓存配合Ehcache使用,能够有效提升Java应用的性能,降低数据库压力,同时Ehcache提供的丰富功能和灵活性使其成为Java缓存领域中的热门选择。在实际项目中,正确配置和使用Ehcache,能够为...

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    `hibernate.cache.use_query_cache`和`hibernate.cache.use_second_level_cache`分别开启了查询缓存和二级缓存。最后,通过`class-cache`元素配置了`EntityClass`的缓存策略,这里使用了"read-write",表示读写操作...

    hibernate二级缓存

    在Hibernate框架中,缓存分为一级缓存和二级缓存。 一级缓存是默认开启的,它与Session对象关联,主要负责在同一个事务内部管理对象的状态。一级缓存会跟踪所有在事务中被修改的对象,确保在事务提交时仅生成必要的...

    Hibernate 一级缓存和二级缓存的区别

    Hibernate 一级缓存和二级缓存的区别

    Hibernate 二级缓存

    Hibernate 二级缓存

    hibernate二级缓存java包下载

    二级缓存是 Hibernate 缓存策略的一部分,它在应用程序的多个会话之间共享数据,进一步优化了数据库访问效率。 二级缓存分为以下关键知识点: 1. **一级缓存与二级缓存的区别**: - 一级缓存:每个 Hibernate ...

    hibernate一级和二级缓存配置与详解

    本篇将深入探讨Hibernate的一级缓存和二级缓存,以及查询缓存的配置和使用。 ### 一级缓存 一级缓存是Hibernate默认提供的缓存,它是Session级别的,每个Hibernate Session都有一个私有的、本地的一级缓存。当我们...

    Hibernate 二级缓存 总结整理

    在处理大数据量或高并发的场景下,为了提高性能和减少数据库负载,Hibernate 提供了二级缓存机制。本文将深入探讨Hibernate的二级缓存,并结合相关源码进行解析。 ### 一、一级缓存与二级缓存 1. **一级缓存...

    springboot+jpa(hibernate配置redis为二级缓存) springboot2.1.4

    通过以上步骤,我们就成功地在Spring Boot 2.1.4.RELEASE项目中配置了使用Redis作为Hibernate二级缓存的环境。这将显著提升数据库查询效率,减少对数据库的压力,尤其在高并发场景下,效果尤为明显。记得在实际生产...

    Spring集成的Hibernate配置二级缓存

    本文将详细探讨如何在Spring集成的Hibernate环境中配置二级缓存,以及其背后的原理和实践。 首先,我们需要了解什么是二级缓存。在Hibernate中,一级缓存是每个Session内部的缓存,它自动管理实体的状态,当一个...

    为Spring集成的Hibernate配置二级缓存

    二级缓存的使用可以显著提升系统性能,特别是在频繁查询相同数据的情况下。然而,需要注意的是,虽然缓存可以提高效率,但也要考虑数据的一致性和并发控制问题,避免出现脏读、不可重复读等问题。因此,在实际应用中...

Global site tag (gtag.js) - Google Analytics