基于hibernate缓存机制的查询性能优化研究

来源 :电脑知识与技术 | 被引量 : 0次 | 上传用户:wh_wzy
下载到本地 , 更方便阅读
声明 : 本文档内容版权归属内容提供方 , 如果您对本文有版权争议 , 可与客服联系进行内容授权或下架
论文部分内容阅读
  摘要:良好的缓存管理机制以及合理的缓存应用模式往往是系统性能提升的关键。而查询性能是一个系统性能表现的重要方面。文章在深入研究Hibernate的缓存机制以及二级缓存的应用策略的同时,提出了两种基于该缓存机制的系统查询性能优化方法。应用结果表明,通过这两种方法系统性能得到了相应的提高。
  关键词:Hibernate;二级缓存;查询性能优化
  中图分类号:TP311文献标识码:A 文章编号:1009-3044(2007)17-31361-02
  Research on the Query Optimization Based on Hibernate Caching Mechanism
  XUE Ying,MIN Lian-ying,QIU Qiao-chun
  (College of Computer Science & Technology, Wuhan University of Technology, Wuhan 430063,China)
  Abstract:The key to improving the performance of system is good caching mechanism and reasonable manage mode. Query performance is the important aspect of the system performance. This article studies the Hibernate Caching Mechanism and the manage Strategy of two level cache, at the same time, puts forward two methods base on this Caching Mechanism to optimize query performance. It turns that the performance of system is improved by these methods.
  Key words:Hibernate; two level cache; Query Optimization
  
  0 引言
  
  Hibernate是一个面向JAVA环境的对象/关系数据库映射工具,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用面向对象编程思维来操纵关系数据库。对象/关系映射(Object/ Relational Mapping,简称ORM)把对象模型表示的对象映射到基于SQL的关系模型结构中去,使得Hibernate可以应用在任何使用JDBC的场合,可以应用到EJB的J2EE架构中,以取代CMP完成数据持久化的重任,也可以整合到J2EE系统中作为持久层框架。
  缓存是数据库数据在内存中的临时容器,它包含了库表数据在内存中的临时拷贝,位于数据库与数据访问层之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高应用的运行性能。
  相对内存操作,数据库调用是一个代价高昂的过程,然而典型企业级应用结构,数据库往往和应用服务器位于不同的物理服务器,这就意味着每次数据库访问都是一次远程调用,数据的打包拆包,网络传输上的延时等消耗都给网络整体性能造成了严重影响。此时,本地内存中的数据缓存的存在价值就显得特别突出。
  对于ORM而言,缓存显得更为重要,它是持久层性能提升的关键。因为相对JDBC的数据存取,ORM的实现往往要借助更加复杂的机制,以实现内部状态的管理、OR关系的映射等。这些额外的开销使得ORM数据访问效率降低,数据缓存是弥补这里产生的性能差距的一个关键策略。特别是对于查询操作相对频繁的系统而言,良好的缓存管理机制以及合理的缓存应用模式往往是性能提升的关键。
  
  1 Hibernate的缓存机制
  
  1.1 持久化层的缓存的范围
  持久层设计中,往往需要考虑几个不同层次中的数据缓存策略。这些层次的划分标准针对不同情况有所差异,一般而言,ORM的数据缓存应包含如下几个层次:
  事物级缓存(Transaction Layer Cache)
  缓存只能被当前事务访问。缓存的生命周期依赖于事务的生命周期,当事务结束时,缓存也就结束生命周期。在此范围下,缓存的介质是内存。事务可以是数据库事务或者应用事务,每个事务都有独自的缓存,缓存内的数据通常采用相互关联的对象形式。
  应用级/进程级缓存(Application/Process Layer Cache)
  缓存被进程内的所有事务共享。这些事务有可能是并发访问缓存,因此必须对缓存采取必要的事务隔离机制。缓存的生命周期依赖于进程的生命周期,进程结束时,缓存也就结束了生命周期。进程范围的缓存可能会存放大量的数据,所以存放的介质可以是内存或硬盘。缓存内的数据既可以是相互关联的对象形式也可以是对象的松散数据形式。对象的松散数据形式有点类似于对象的序列化数据,但是对象分解为松散的算法比对象序列化的算法要求更快。
  集群级缓存(Cluster Layer Cache)
  在集群环境中,缓存被一个机器或者多个机器的进程共享。缓存中的数据被复制到集群环境中的每个进程节点,进程间通过远程通信来保证缓存中的数据的一致性,缓存中的数据通常采用对象的松散数据形式。对大多数应用来说,应该慎重地考虑是否需要使用集群范围的缓存,因为访问的速度不一定会比直接访问数据库数据的速度快多少。
  持久层提供以上多种层次的缓存。如果在事务级缓存中没有查到相应的数据,还可以到进程级或集群级缓存内查询,如果还是没有查到,那么只有到数据库中查询。事务级缓存是持久化层的第一级缓存,通常它是必需的;进程级或集群级缓存是持久化层的第二级缓存,通常是可选的。
  1.2 hibernate缓存机制
  Hibernate提供了两种缓存,第一种是Session的缓存,又称为一级缓存。由于Session对象的生命周期通常对应一个数据库事务或者一个应用事务,因此它的缓存是事务范围的缓存。第一级缓存是必需的,不允许而且事实上也无法卸除。在第一级缓存中,持久化类的每个实例都具有唯一的OID。如图1所示:
  图1 hibernate的二级缓存结构图
  第二种缓存是SessionFactory的缓存,又可以分为两类:内置缓存和外置缓存。SessionFactory的内置缓存和Session的缓存在实现方式上比较相似,前者是SessionFactory对象的一些集合属性包含的数据,后者是指Session的一些集合属性包含的数据。SessionFactory的内置缓存中存放了映射元数据和预定义SQL语句,映射元数据是映射文件中数据的拷贝,而预定义SQL语句是在Hibernate初始化阶段根据映射元数据推导出来,SessionFactory的内置缓存是只读的,应用程序不能修改缓存中的映射元数据和预定义SQL语句,因此SessionFactory不需要进行内置缓存与映射文件的同步。
  SessionFactory的外置缓存是一个可配置的插件。在默认情况下,SessionFactory不会启用这个插件。外置缓存的数据是数据库数据的拷贝,外置缓存的介质可以是内存或者硬盘。SessionFactory的外置缓存也被称为Hibernate的第二级缓存。
  由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此第二级缓存是进程范围或者集群范围的缓存。二级缓存将由从属于本SessionFactroy的所有Session实例共享,因此有时成为SessionFactory Level Cache。这个缓存中存放的对象的松散数据。第二级对象有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。缓存适配器(Cache Provider)用于把具体的缓存实现软件与Hibernate集成。第二级缓存是可选的,可以在每个类或每个集合的粒度上配置第二级缓存。
  Hibernate还为查询结果提供了一个查询缓存,它依赖于第二级缓存。
  1.4 二级缓存应用策略。
  二级缓存在一个SessionFactory中有效,是优化的重中之重,因此,各类策略也考虑的较多,但是并非所有的情况都适合于使用二级缓存,需要根据具体情况来决定。同时可以针对某一个持久化对象配置其具体的缓存策略。
  适合于使用二级缓存的情况:
  (1)数据不会被第三方修改;
  一般情况下,会被hibernate以外修改的数据最好不要配置二级缓存,以免引起数据不一致问题。但是如果此数据因为性能的原因需要被缓存,同时又有可能被第三方比如SQL修改,也可以为其配置二级缓存。只是需要在sql执行修改后手动清除cache,以保证数据的一致性。
  (2)数据大小在可接收范围之内;
   如果数据表数据量特别巨大,不适合配置二级缓存。原因是缓存的数据量过大可能会引起内存资源紧张,反而降低性能。
  如果数据表数据量特别巨大,但是经常使用的只是较新部分的数据,也可以为其配置二级缓存。但是必须单独配置其持久化类的缓存策略,比如最大缓存数、缓存过期时间等,将这些参数降低至一个合理的范围(太高会引起内存资源紧张,太低了缓存的意义不大)。
  (3)数据更新频率低;
   对于数据更新频率过高的数据,频繁同步缓存中数据的代价可能和从查询缓存中的数据获得的好处相当,坏处益处相抵消。此时缓存的意义也不大。
  (4)非关键数据(不是财务数据等)
   财务数据等是非常重要的数据,绝对不允许出现或使用无效的数据,所以此时为了安全起见最好不要使用二级缓存。
  
  2 基于缓存的优化策略
  
  =查询性能往往是一个系统性能表现的重要方面。相对数据库的更新、删除操作而言,查询机制的优劣很大程度决定了系统的整体性能。
  2.1 查询缓存的应用
  对于经常使用的查询语句,如果启用了查询缓存(Query Cache),当第一次执行查询语句时,hibernate会把查询结果存放在第二级缓存中。以后再执行该查询语句时,只需从缓存中获得查询结果,从而提高性能。
  查询缓存策略的一般过程如下:
  (1)Query Cache保存了之前查询执行过的Select SQL以及结果集等信息,组成一个Query Key。Query Key包括条件查询的请求一般信息:SQL, SQL需要的参数,记录范围(起始位置rowStart,最大记录个数maxRows)等。
  (2)当再次遇到查询请求的时候,就会根据Query Key 从Query Cache找,如果存在就返回这个结果列表;如果不存在,查询数据库获取结果列表,把整个结果列表根据Query Key放入到Query缓存中。
  (3)但是两次查询之间,数据表发生数据变动的话,Hibernate就会自动清除Query Cache中对应的Query Key。
  为了启用Query Cache,我们需要在hibernate.cfg.xml中进行配置,参考配置如下(只列出核心配置项):
  
  
  …………
  true
  …………
  

  

  应用程序中必须在查询执行之前,将Query.Cacheable设置为true,而且每次都应该这样。比如:
  ………
  Query query=session.createQuery(hql).setInteger(0.15);
  query.setCacheable(true);
  ………
  但是,Query Cache只在特定的条件下才会发挥作用,而且要求相当严格:
  (1)完全相同的Select SQL重复执行。
  (2)重复执行期间,Query Key对应的数据表不能有数据变动(比如添、删、改操作)。
  并且,查询缓存在一个交易系统(数据变更频繁,查询条件相同的机率并不大)中可能会起反作用:它会白白耗费大量的系统资源但却很难发挥优势。
  2.2 数据查询方法的选用
  完成同样的查询,Hibernate提供了可供选择的一些方式,但具体使用什么方式,可能对性能和代码都会有影响。
  (1)Session.load/get方法均可以根据指定的实体类和id从数据库读取记录,并返回与之对应的实体对象。
  (a)Session. load
  在执行session.load时,Hibernate首先从当前session的一级缓存中获取id对应的值,在获取不到的情况下,将根据该对象是否配置了二级缓存来做相应的处理,如配置了二级缓存,则从二级缓存中获取id对应的值,如仍然获取不到则还需要根据是否配置了延迟加载来决定如何执行,如未配置延迟加载则从数据库中直接获取,在从数据库获取到数据的情况下,Hibernate会相应的填充一级缓存和二级缓存,如配置了延迟加载则直接返回一个代理类,只有在触发代理类的调用时才进行数据库查询的操作。如果未能发现符合条件的记录, load方法会抛出一个ObjectNotFoundException。
  (b)Session.get
  在执行Session.get时,和Session.load不同的就是get方法则仅仅在内部缓存中进行数据查找,如没有发现对应数据,将越过二级缓存,直接调用SQL完成数据读取。直接从数据库中获取id对应的值。如果未能发现符合条件的记录返回null,而且get方法永远直接返回实体类。
  (2)Query.list / Query.iterate方法均可根据指定条件查询并返回符合条件的实体对象集。
  (c)Query.list
  在执行Query.list时,Hibernate的做法是首先检查是否配置了查询缓存,如配置了则从查询缓存中通过一条sql语句获取所有符合条件的记录,并构造相应的实体对象,然后将其纳入缓存。如获取不到则从数据库中进行获取,从数据库获取到后Hibernate将会相应的填充一级、二级和查询缓存,如获取到的为直接的结果集,则直接返回,如获取到的为一堆id的值,则再根据id获取相应的值(Session.load),最后形成结果集返回。
  (d)Query.iterate
  在执行Query.iterate时,和Query.list的不同的在于从数据库获取的处理上,Query.iterate向数据库发起的是 select id from这样的语句,也就是它是先获取符合查询条件的id,之后在进行iterate.next调用时才再次发起session.load的调用获取实际的数据。iterate方法首先在本地缓存中根据id查找对应的实体对象是否存在(类似Session.load方法),如果缓存中已经存在对应的数据,则直接以此数据对象为查询结果,如果没有找到,再执行相应的Select语句获得对应的库表记录。(iterate方法如果执行了数据库读取操作并构建了完整的数据对象,也会将其查询结果纳入缓存)。
  而且,通过iterate,配合缓存管理API,在海量数据查询中可以很好的解决内存问题,如:
  while(it.hasNext()){
  YouObject object = (YouObject)it.next();
  session.evict(youObject);
  sessionFactory.evice(YouObject.class, youObject.getId());}
  如果用list方法,很可能就出OutofMemory错误了。
  可见,在拥有二级缓存并且查询参数多变的情况下,Query.iterate、Session. load会比Query.list及Session.get更为高效。
  
  3 结束语
  
  在实际开发中,运用好缓存可以让系统性能得到良好的提升。可缓存也有它的局限性,什么情况用什么情况不用,都要结合实际情况来考量。很多时候我们是在效率与安全/准确性上找一个平衡点,无论如何,优化都不是一个纯技术的问题,应该对应用和业务特征有足够的了解,如果违背了相关的缓存机制,可能会得到负面效果,所以必须充分考虑实际情况来灵活运用缓存并发挥它的优势。
  
  参考文献:
  [1]Christian Bauer,Gavin King. Hibernate in Action[M].Manning Publications,Greenwich.2005
  [2]赵东波,何源源,基于Hibemate的效率查询的研究和应用[J],科学技术与工程,2007.
  [3]徐凯声, 王荣存,基于语义缓存技术的hibernate查询缓存机制研究[J], 交通与计算机,2006.(4).
  [4]夏昕,曹晓钢,唐勇.深入浅出Hibernate[M].电子工业出版社,2005.
  [5]John Ferguson Smart,Speed Up Your Hibernate Applications with Second-Level Caching,http://www.devx.com/dbzone/Article/29685
  注:本文中所涉及到的图表、注解、公式等内容请以PDF格式阅读原文。
其他文献
摘要:短信技术除了在人们日常的信息交流外,还可以在企业生产管理中得到广泛的应用。本文就SMGP协议、SP接入技术以及它们在电信业务支撑系统中的实现方法做详细说明。  关键词:短信技术;SP;SPMS;SMGP协议  中图分类号:TP393文献标识码:A 文章编号:1009-3044(2007)17-31277-03  The Application of PHS SMS SP Access Tec
期刊
摘要:Java语言凭借跨平台、面相对象、功能强大等优点,已经成为现在最流行的语言之一。在J2EE web项目中,有一种常见的应用被称作作业调度的应用。文中对作业调度的应用背景进行了归纳总结,并结合实例对作业调度的实现步骤进行了介绍,有助于读者从整体上快速掌握作业调度的概念和实现。同时只要对实例进行简单的修改就可以进行实际应用,具有较强的适用价值。  关键词:作业调度;Quartz;Java邮件服务
期刊
摘要:为了解决高校等机构学位论文的查询问题,运用ASP技术及SQL SERVER数据库技术,设计并开发了基于B/S结构的高校学位论文检索系统。所开发的系统运行稳定,功能齐全,很好的满足了学位论文的查询需求,为学术文献的充分利用提供了有力支撑。  关键词:学位论文检索;ASP技术;SQL Server;B/S模式  中图分类号:TP392:J642.477文献标识码:A 文章编号:1009-3044
期刊
摘要:本文介绍了一种基于ARM7TDMI处理器的数据采集模块的实现方法。该模块可以对电压、电流、热电阻、热电偶、开关量等多种物理量进行测量。ARM处理器与数据采集模块之间采用模拟SPI协议进行数据传输。为了实现高精度,采用了24位A/D。经过对电路的多次改进,该模块目前已能测准到万分之一的精度,优于现在的工业标准。  关键词:ARM;多通道;高精度;数据采集  中图法分类号: TP806文献标识码
期刊
摘要:Excel是微软的办公自动化软件的一个组件,是用于数据处理的电子表格软件,而ADO是访问和操作数据库的方法。通过一个课程信息管理程序的设计对于在Delphi中如何利用ADO组件来访问Excel文件的技术方法与实现步骤进行了详细阐述。  关键字:ADO;Excel;访问  中图法分类号:TP311文献标识码:B文章编号:1009-3044(2007)17-31332-02  Visits th
期刊
摘要:XML正成为Internet上数据描述和交换的主要标准,因此对面向对象XML存储研究变的很重要。通过扩展DTD的支持使得XML文档具有面向对象的特性,通过对扩展DTD的解析,从而获取XML模式信息,这些信息不仅支持查询语言和XML文档的有效性检查,而且支持新存储模式建立。如何有效的获取这些信息成为研究重点。  关键字:JavaCC;JJTree;扩展DTD;解析  中图分类号:TP391文献
期刊
摘要:实验室管理工作的主要内容包括设备、教学任务、实验项目、规章制度等。由于采用人工管理,管理信息量大、操作繁琐,设备的利用率很难提高,所以建设实验室管理信息系统就势在必行。本文主要探讨了系统开发的目标,可行性分析,以及系统的总体设计,包括概念模型的分析与数据库的开发。  关键词:实验室系统;可行性;数据库  中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)17-313
期刊
摘要:文中分析了企业应用系统集成的必要性和点对点集成及EAI方法的不足。探讨了面向服务的架构模型及其集成思想。提出了基于SOA的企业应用系统集成的解决方案,并给出了一个具体应用集成的开发示例。充分论证了基于SOA的应用系统集成开发的优越性和必然性。Web服务技术是实现SOA的最佳实践。  关键词:面向服务的架构;服务;Web服务;EAI  中图分类号:TP311文献标识码:A 文章编号:1009-
期刊
摘要:介绍了在VC++.net的运行环境下运用拆分窗口功能实现界面切换的步骤及具体实现方法,并给出了关键的实现函数与事例。  关键词:VC++.net;界面切换;拆分窗口  中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)17-31382-01  Realizing of Changing Interface to Use the Function of Separat
期刊
摘要:0-1背包问题是经典的NP问题。本文对0-1背包问题的动态规划算法进行了分析,用Visual C++实现该算法。  关键词:0-1背包;动态规划  中图分类号:TP311文献标识码:A文章编号:1009-3044(2007)17-31378-02  The Dynamic Programming Algorithms of 0-1 Knapsack Problem Based on Visu
期刊