数据库性能之--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延迟加载

ibatis延迟加载实现分析
  • prince2270
  • prince2270
  • 2010年10月29日 15:26
  • 4015

Ibatis的延迟加载

我们知道Hibernate中有get()和load()两种方法,load()采用的是延迟加载的机制,同样的对于Ibatis也有着自己的延迟加载机制, 什么是延迟加载呢,就是将暂时不需要的对象不真正的...
  • hai_cheng001
  • hai_cheng001
  • 2013年12月16日 21:42
  • 1702

ibatis的延迟加载机制

        在DomainMoudel中,经常会碰到一个域对象中包含另外一个域对象的列表,例如:一个blog的文章会有多个回复。我们就拿blog来做实例说明,情形一:获取blog的文章信息展示给用...
  • oswin_jiang
  • oswin_jiang
  • 2009年04月30日 15:31
  • 4881

ibatis 延迟加载

ibatia 延迟加载为一对多的时候使用最为方便  upBankAccount: 为实体中的新的对象 bankAccountId: 为对应的查询字段...
  • qq_33238935
  • qq_33238935
  • 2017年01月18日 20:58
  • 146

ibatis延迟加载

ibaits中延迟加载的含义是在使用到某个对象时,再去加载具体的数据(执行查询语句),否则不会对数据进行加载。     ibatis查询数据库时,会调用ResultMap.getResults(St...
  • duwenchao1986
  • duwenchao1986
  • 2013年02月02日 17:17
  • 1159

iBATIS七大特性

iBATIS特性有哪些呢?正如你所知道的,可以在任何系统中使用iBATIS。像iBATIS这样一个框架能够使你的应用从架构级别上开始受益是什么原因呢?来开始我们的介绍吧。 1简单性 ...
  • wanghuan203
  • wanghuan203
  • 2012年11月30日 22:42
  • 1603

ibatis批量插入数据-iterate标签详解及应用

Sql代码   insert into       tb_name(col1, col2, col3)       values       (col1_v, col2_v, col3_v), ...
  • shixiaoguo90
  • shixiaoguo90
  • 2015年12月02日 15:14
  • 2617

JDBC iBatis Hibernate的区别及各自的优缺点总结

1.   JDBC: 面向数据的,SQL直接写在代码中,不方便使用维护,但效率高安全性好        try(PreparedStatement psts = connection.prepareS...
  • cleble
  • cleble
  • 2015年09月17日 11:33
  • 373

iBatis相关总结

一,iBatis简介 相对Hibernate和Apache OJB 等“一站式”ORM(对象关系映射 Object Relational Mapping,简称ORM)解决方案而言,ibatis 是一...
  • shuaishuai123485615
  • shuaishuai123485615
  • 2017年03月30日 15:41
  • 287

seajs开篇:我为什么学习seajs,因为它的"预先下载,延迟执行"特性

之前参与的2个项目都用到了js模块化工具requireJS框架,工作之余学习了这个框架,也熟悉了requireJS的基本用法以及AMD规范。本来对seaJS没有太大的兴趣,知道它实现了CMD规范,功能...
  • aitangyong
  • aitangyong
  • 2015年10月20日 19:22
  • 867
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:数据库性能之--iBatis延迟加载
举报原因:
原因补充:

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