数据库性能之--iBatis延迟加载

转载 2012年03月30日 22:39:28

转载于:http://zhaohe162.blog.163.com/blog/static/38216797201112122632893/?suggestedreading&wumii

 

(1)
ibatis一对多查询带来的问题:
如果在数据库中,Account记录对应着相关的多条Order记录,而Order又对应着相关的多条OrderItem记录,可以为这些记录建立关系,当我们请求一条Account记录时,可以一并获取所有的Order和OrderItem记录。下面的代码清单显示了如何定义我们的SQL映射:
 
先来看看结果映射(result map,即上面的ResultAccountInfoMap,ResultOrderInfoMap和ResultOrderItemMap),前两个Map都用到了select特性。这个特性告诉iBATIS,属性的值将由另一个映射语句来设置,语句的名称就是select特性的值。
例如,我们执行getAccountInfoList语句时,ResultAccountInfoMap结果映射有一个子元素:
 
它的作用是告诉iBATIS,account对象的orderList属性的值由ChgetOrderInfoList语句来设置,同时把accountId列的值传给ChgetOrderInfoList作为参数。
这个功能给我们带来便利的同时,也带来了两个问题。
首先,创建包含大量对象的列表可能会消耗大量的内存。
其次,这种方法会导致数据库的I/O问题,其原因是所谓的“N+1 Select”现象.
 
(2)
N+1现象:
2.1数据库I/O
数据库I/O是数据库使用状况的一项指标,也是数据库性能的主要瓶颈之一。在读取或写入数据库时,数据必须要经历从磁盘到内存或者从内存到磁盘的转换,这个过程是比较耗时的。在程序中使用缓存可以减少对数据库的访问.
2.2
在使用关联数据时,可能会遭遇数据库I/O问题(N+1现象)。考虑一下这个场景:有1000个Account,每一个关联了1000个Order,而每个Order则包含25个OrderItem。如果尝试将所有这些数据加载到内存,执行的SQL语句要超过1000000行(1条用来查询Account,1000条用于Order,1000000条用于OrderItem),而创建的对象大约为2500万——如果你真敢这么做,等你的系统管理员收拾你吧。
 
(3)
解决由关联数据查询时,引起的N+1现象,可以用延时加载。
延迟加载(Lazy loading)
首先来看看延迟加载。如果不是对所有数据都马上用到,那么延迟加载是有用的。例如,我们的程序首先在一个网页显示所有Account,然后销售代理(我们的客户)可以点击一个Account来查看该Account的Order列表,然后可以再点击一个Order来查看其所有的OrderItem信息。在这种情况下,每次都仅查询一个列表。这是对延迟加载的合理使用。
当用户 getSqlMapClientTemplate().queryForList(”getAccountInfoListN”)的时候,实际上只是执行了查询account表的信息,而当我们执行代码--在account对象中getOrderList()的时候,才会执行后面的查询orderList对象的语句;这样在首页访问 account列表的时候就不用加载orderList的信息,而在点击单个account浏览的时候需要用到orderList的时候,才会执行 getOrderList的查询操作,把列表信息给出来。这样做明显的减少了代码的负责程度,按需提取信息也提升了系统的性能!
采用延时加载,上面的xml定义,可以改为:


且须在ibatis的配置文件中定义如下:
<settings
  ……
     lazyLoadingEnabled=”true”
     enhancementEnabled=”true”
     ……/>
        lazyLoadingEnabled设置系统是否实现延迟加载机制,enhancementEnabled设置是否用字节码强制机制,通过字节码强制机制可以为lazy loadding带来性能方面的改进。
 
(4)
在加载复杂属性时可能出现两方面的问题,一是对数据库的访问,二是创建对象时对内存的消耗。我们可以采用延迟加载或Join的方法来解决这些问题,但是两者都不是万灵药。延迟加载的原理时推迟对复杂属性的加载,以减少对数据库的访问和对象的创建,但它的前提是复杂属性不会马上用到,否则的话,延迟就失去意义。Join的原理是通过一条SQL语句加载所有数据,这样可以大幅度减少对数据库的访问量,它的前提是对象的数量不会太多。该如何选择呢?下面的表格给出了简单的原则:
 
图4简单的原则
 
另外,我觉得还有一条很重要的原则,那就是永远只加载必需的数据。以上面的例子来说,我们不太可能会同时显示1000个Account给用户看,这时就不要同时加载1000个Account的数据了,可以通过分页只显示50条数据,在此基础上再应用延迟加载或Join效果会很不错。
 
(5)
结合第二章笔记,可知:
提升数据库查询性能的方式有三:
1。分页查询。(最实际有效)
2。延时加载。
3。利用cache查询(对修改次数很少的数据)。

.

[ibatis]:延迟加载和N+1问题

数据库I/O可以很好的度量数据库的使用情况,同时也是影响数据库性能的主要瓶颈之一。数据从磁盘到内存或则从内容写到磁盘这种操作时非常耗时。高速缓存能很好的应到到这一问题来提高性能。    N+1问题是...
  • zztp01
  • zztp01
  • 2011年11月17日 14:03
  • 551

前端性能优化--延迟加载js、css、图片等组件

上一张讲了关于图标使用雪碧图或者内联图片可以提升性能,但是在工作和开发中我们可能还是会遇到,一个界面加载很多js、css、大的背景图片的时候,这里我给大家提供一种思路,延迟加载,意思就是说,页面一开始...
  • wzgdjm
  • wzgdjm
  • 2016年03月04日 08:38
  • 3297

前端性能优化之 —— 图片延迟加载 (原理以及实现方式)

前端开发的时候,有些列表页面可能会有很多图片需要加载。一次加载太多图片,会占用很大的带宽,影响网页的加载速度。 这时候我们想到一种方式,让用户浏览到什么地方,就加载该处的图片。 这里写了一个简单的...

Hibernate性能调优--关联实体的延迟加载

默认情况下,Hibernate也会采用延迟加载来加载关联实体,不管是一对多关联、还是一对一关联、多对多关联,Hibernate 默认都会采用延迟加载。 对于关联实体,可以将其分为两种情况: 关...

延迟加载解决offset过大导致的分页性能问题

当我们展示一个列表中的内容时,难免会遇到分页问题,因为列表中的内容数量可能很多,但是用户能一次看到的界面大小是有限的,不可能一个界面展示所有的内容,从后端一次性取太多的数据也会给后端造成额外的压力。 ...

Hibernate性能优化之————延迟加载与抓取策略

Hibernate性能优化之————延迟加载与抓取策略   懒加载【延迟加载】: 主要目的: 为了推迟与数据库交互的时间,提高系统的系能 它是hibernate为提高程序执行效率而提供的一种...
  • w_l_j
  • w_l_j
  • 2011年12月14日 15:51
  • 3195

web前端性能优化(二)--图片的延迟加载

网站性能优化: 1、尽量减少向服务器端请求的次数"减少HTTP请求" 2、css/js文件进行合并 3、ICON图片进行合并->雪碧图/css script 4、图片的延迟加载...

Sencha Touch延迟加载模块中的小类提高程序进入每个模块时性能

上一篇文章我写了如何提高Sencha Touch在进入程序时的性能,但是后来发现,虽然进入程序时候性能提高了,但是初始化Controller的任务分摊到各个模块了,使得第一次进入模块的时候变得比原来慢...

Hibernate性能调优--集合属性的延迟加载

Hibernae的延迟加载是一个非常常用的技术,实体的集合属性默认会被延迟加载,实体所关联的实体默认也会被延迟加载。Hibernate通过这种延迟加载来降低系统的内存开销,从而保证 Hibernate...

Web性能优化系列(3):如何延迟加载JS

摘要: 延迟加载JS JavaScript的延迟加载是那些在web上,能让你想抓狂地去寻找解决方案的问题之一。 很多人说“那就用defer”或“async”,甚至有些人说“那就将你的ja...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:数据库性能之--iBatis延迟加载
举报原因:
原因补充:

(最多只允许输入30个字)