网上购物系统中信息检索性能优化

点赞:4270 浏览:11862 近期更新时间:2024-02-05 作者:网友分享原创网站原创

[摘 要]文中对Hibernate检索策略中内存浪费的原因进行了研究,提出了采用查询缓存和集合过滤的方法进行查询优化,降低了访问数据库的频率且避免了在数据查询检索过程中加载不需要的Ja对象,从而降低了的内存消耗.最后,通过查询网上购物系统中客户的定单记录试验验证了优化方式的有效性.

[关 键 词]Hibernate查询缓存集合过滤客户定单

在分层的软件架构中持久化层封装了所有数据访问细节,是对象-关系映射(ORM)的中间件,Hibernate是一种ORM中间件工具,它对JDBCAPI进行了封装,负责Ja对象的持久化.Hibernate通过Session接口提供了基本的保存、更新、删除和查询,Session具有一个缓存,位于缓存中的对象处于持久化状态,它和数据库中的相关记录对应,Session能够在某些时间点按照缓存中持久化对象的属性变化来同步更新数据库.在Session的缓存中存放的是相互关联的对象图.在默认情况下,当Hibernate从数据库中加载Ja对象时,会同时加载所有关联的Ja对象,从而影响了系统的性能.本文以查询网上购物系统中的客户(Customer)和定单(Order)信息为例,介绍如何设置Hibernate的检索策略,以优化查询性能.

网上购物系统中信息检索性能优化参考属性评定
有关论文范文主题研究: 关于数据库的论文范文素材 大学生适用: 专升本论文、高校毕业论文
相关参考文献下载数量: 57 写作解决问题: 如何怎么撰写
毕业论文开题报告: 文献综述、论文目录 职称论文适用: 杂志投稿、职称评中级
所属大学生专业类别: 如何怎么撰写 论文题目推荐度: 免费选题

一、常用查询方法

设计两个数据库表,表名为CUSTOMERS和ORDERS,它们包含的基本字段及之间的关系如图1:

Hibernate查询客户和定单信息的步骤为:

1.运用反射机制,获得customer对象的类型Customer.class.

2.参考对象-关系映射元数据,了解到和Customer类对应的表为CUSTOMERS表,类Customer与类Order关联,类Order和ORDERS表对应,ORDERS表中外键CUSTOMER_ID参照CUSTOMERS表的主键ID.

3.根据映射信息,生成SQL语句:

select*fromCUSTOMERS,

select*fromORDERSwhereCUSTOMERS_ID等于1.

4.调用JDBCAPI,执行以上SQL语句.Hibernate在检索与Customer关联的Order对象时,使用默认的立即检索策略.这种检索策略存在三大不足:

(1)select语句的数目太多需要频繁地访问数据库,会影响检索性能.

(2)在应用逻辑只需要访问Customer对象,而不需要访问Order对象的场合,加载Order对象完全是多余的操作,这些多余的Order对象浪费了许多内存空间.

(3)检测定这个Customer对象与500个Order对象关联,就会加载500个Order对象.在实际应用中往往只需要访问Orders集合中的部分Order对象.例如访问客户定单金额大于100的Order对象,此时调用customer.getOrders().iterator()方法会影响运行时性能.因为它会加载应用程序不需要访问的Order对象.

延迟检索策略能避免多余加载应用程序不需要访问的关联对象;但当采用延迟检索策略时,应用程序如果希望访问游离状态的写作技巧类实例,必须保证它作持久化状态时已经被初始化.迫切左外连接检索策略则利用SQL的外连接查询功能能够减少select语句的数目;但缺点在于可能会加载应用程序不需要访问的对象,浪费许多内存空间,更杂的数据库表连接也会影响检索性能.

二、查询性能优化

Hibernate主要可从以下两方面来优化查询性能.

1.使用查询缓存降低访问数据库的频率,减少select语句的数目;对于经常使用的查询语句如果启用了查询缓存.当第一次执行查询语句时,Hibernate会把查询结果存放在第二级缓存中.以后再次执行该查询语句时.只需从缓存中获得查询结果从而提高查询性能.对查询语句启用查询缓存的步骤如下:

(1)配置第二级缓存,在Customer.hbm.xml和Order.hbm.xml映射文件中分别为Customer类、Customer类的orders集合以及Order类设置第二级缓存,


Customer.hbm.xml设置第二级缓存代码:

name等于“orders”

>

Order.hbm.xml设置第二级缓存代码:

(2)在Hibernate的配置文件hibernate.properties中选用EHCache和设置查询缓存属性:

hibernate.cache.provider_class等于..hibernate.cache.EhCacheProvi

Hibernate.cache.use_query_cache=ture

(3)对于希望启用查询援存的查询语句.调用接口Query的setCacheable()方法:

QueryorderByMoneyQuery等于session.createQuery(“fromOrderowhereo.money>:money”),

orderByMoneyQuery.setInteger(“money”,money),

orderByMoneyQuery.setCacheable(true),

如果希望更加精粒度地控制查询援存,可以设置缓存区域.

orderByMoneyQuery.setCacheRegion(“orderQueries”),

Hibernate提供了三种和查询相关的缓存区域

①默认的查询缓存区域:..hibernate.cache.StandardQueryCache

②用户自定义的查询缓存区域:如“orderQueries”

③时间戳缓存区域:..hibernate.cache.UpdateTimestampCache

默认的查询缓存区域以及用户自定义的查询缓存区域部用于存放查询结果.而时间戳缓存区域存放了对与查询结果相关的表进行插入、更新或删除操作的时间戳.Hibernate通过时间戳缓存区域来判断被缓存的查询结果是否过期,它的运行过程如下:

在T1时刻执行查询语句,把查询结果存放在QueryCache域.该区域的时间戳为TI时刻.

在T2时刻对与查询结果相关的表进行插入、更新或删除操作.Hibernate把T2时刻存放在UpdateTimestampCache区域.

在T3时刻执行查询语句前,先比较QueryCache区域的时间戳和UpdateTimestampCache区域的时间戳.如果T2>T1,那么就丢弃原先存放在QueryCache区域的查询结果,重新到数据库中查询数据再把查询结果存放在QueryCache区域;如果T2<T1,直接从QueryCache区域获得查询结果.


由此可见,如果当前应用进程对数据库的相关数据做了修改,Hibernate会自动刷新缓存的查询结果.若其他应用进程对数据库的相关数据做了修改,Hibernate无法监测到这一变化,此时由应用程序负责监测这一变化(如通过发送和接收事件或消息机制),然后手工刷新查询结果.Query接口的setForceCacheRefresh(true)方法允许手工刷新查询结果,它使得Hibernate丢弃查询缓存区域中已有的查询结果,重新到数据库中查询数据.再把查询结果存放在查询缓存区域中.

2.使用集合过滤避免多余加载程序不需要访问的数据

使用集合过滤可以很好避免加载多余的Order对象,其主要代码如下:

Listresult等于session.createFilter(customer.getOrders(),“wherethis.money>100orderbythis.money”).list(),

Iteratorit等于result.iterator(),

While(it.hasNext()){

Orderorder等于(Order)it.next(),

}

代码中Session接口的createFilter方法用来过滤集合,它具有以下优点:

(1)如果Customer对象orders集会已经被初始化,为了保证Session的缓存中不会出现OID相同的Order对象,Query的list()方法不会再创建Order对象,仅仅返回已经存在的Order对象的引用.其运行时行为如图2所示:

(2)如果Customer对象的orders集合还没有被初始化,Query的list()方法会创建相应的Order对象.但是不会初始化Customer对象的orders集合.其运行时行为如图3所示:

三、试验分析

这里通过检索某客户定单金额大于100元的所有定单试验来验证改进前后的性能情况.

按照立即检索策略我们一次从数据库中读取客户ID等于1的所有订单(共500条记录)中金额大于100元的所有记录(共200条记录),然后按照改进后的方式我们从数据库中读取上述记录.考虑到Ja虚拟机的垃圾收集机制和降低试验误差,两种的检索方式分别做五次,取平均值.开发软件采jdk1.5.0+Tomcat5.0.24,数据库采用MySQL5.0.2.

结果如下:

1.采用立即检索策略

第一次查询前、后Ja虚拟机内存占用率分别为:23065K、26643K,查询结果占3578K,

第二次查询前、后Ja虚拟机内存占用率分别为:22990K、26662K,查询结果占用3672K,

第三次查询前、后Ja虚拟机内存占用率分别为:22998K、26580K,查询结果占用3590K,

第四次查询前、后Ja虚拟机内存占用率分别为:22967K、26597K,查询结果占用3612K,

第五次查询前、后Ja虚拟机内存占用率分别为:22978K、26574K,查询结果占用3596K,

查询结果平均内存占用为3609K.

2.同时采用查询缓存和集合过滤检索策略

第一次查询前、后Ja虚拟机内存占用率分别为:23070K、24032K,查询结果占用962K,

第二次查询前、后Ja虚拟机内存占用率分别为:23012K、23909K,查询结果占用897K,

第三次查询前、后Ja虚拟机内存占用率分别为:22993K、23949K,查询结果占用956K,

第四次查询前、后Ja虚拟机内存占用率分别为:22812K、23747K,查询结果占用935K,

第五次查询前、后Ja虚拟机内存占用率分别为:22991K、23904K,查询结果占用913K,

查询结果平均内存占用为932K.

从试验结果可知:采用本文所述的方式进行查询优化操作,节约了大量的内存,当进行大量数据查询时,效果十分明显.

四、结语

Hibernate在持久化过程中由于采用立即检索策略,导致加载了不需要的Ja对象和频繁访问数据库,占用了大量的内存.采用本文介绍的查询缓存和集合过滤检索策略,可以解决立即检索策略中存在的问题,并且没有增加开发人员的工作量,是减少内存消耗的有效方法.