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

mybatis优化(转)

 
阅读更多

 

最近测试发现个myBatis 有个比较严重的性能问题, 描述如下:

1. define a bean class
public class Bean {
private int id;
private String desc;
private long price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public long getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
}

2.
如果在这个Bean定义中,存在一个属性没有 Getter方法 在运行过程中, Mybatis 会表现为把 class Bean 确定成一个ComplexAccessPlan的对象。那么, MybatisBean对象填充SQL执行后的返回结果会造成比较严重的性能问题。 复杂对象填充Bean的结果在性能上表现比较差一点。 这个性能差异随着需要设置属性数量的增加, 性能成正比的下降。 目前我测试的结果是10个属性情况下影响大约 5-6%的执行时间, 如果属性增加到 84个(中文站的offer对象),他的性能会导致超过30%的下降。 具体的原因, 我会如下解释:


com.mybatis.sqlmap.engine.accessplan.AccessPlanFactory Line 60

if (bytecodeEnhancementEnabled) {
try {
plan = new EnhancedPropertyAccessPlan(clazz, propertyNames);
} catch (Throwable t) {
try {
plan = new PropertyAccessPlan(clazz, propertyNames);
} catch (Throwable t2) {
plan = new ComplexAccessPlan(clazz, propertyNames);
}
}
}

com.mybatis.common.beans.ClassInfo Line256
public Method getGetter(String propertyName) {
Method method = (Method) getMethods.get(propertyName);
if (method == null) {
throw new ProbeException("There is no READABLE property named '" + propertyName + "' in class '" + className + "'");
}
return method;
}

class EnhancedPropertyAccessPlan/PropertyAccessPlan call com.mybatis.common.beans.ClassInfo.getGetter(String) that cause an exception when a bean have no Getter method, AccessPlan object choose ComplexAccessPlan.

3.
根据以上的代码, 我们还可以得出如下结论(这是我给MYBATIS开发团队的邮件部分, 不翻译:)):
IBtatis automatic decide a simple bean that property have no Getter method to be Complex type. Mybatis does not prompt any warning enhancementEnable option will be skipped. I think these mybatis exception handling is not smooth. and If user's bean loose some Getter method, a common user does not know why mybatis performance become bad.
就是一个对象由于Getter方法的缺失, Mybatis把这个对象的当做复杂对象, 从而, 导致enhancementEnable=true(bean对象字节增加功能, 有兴趣的同学可以看看CGLIBBulkBean的使用)的定义失去了任何作用, 进一步导致MYBATIS的性能下降。

针对我们发现的问题, 我们建议如下解决问题:
1.
任何被Mybatis 使用的对象属性必须定义完整的Setter/Getter方法
2.
避免使用自定义类型的对象属性
3.
如果部分属性需要被适当处理后才能使用的, 比如表中有一个字段price, 但是我们需要使用的是Money对象, 请按如下方式使用。primitivePrice作为数据库使用的属性, price作为应用程序使用的属性。
public class Bean {
private Money price = null;
private long primitivePrice;
public Money getPrice() {
if (price == null) {
this.price = new Money(0, 0);
this.price.setCent(primitivePrice);
}
return price;
}

public void setPrice(Money price) {
if (price == null) {
this.price = new Money(0, 0);
} else {
this.price = price;
}
this.primitivePrice = price.getCent();
}

public void setPrimitivePrice(long price) {
this.primitivePrice = price;
}
public long getPrimitivePrice() {
return this.primitivePrice ;
}
}
======================================================================
Mybatis on Oracle
的性能优化
我们先主要看2个参数
1.defaultRowPrefetch of oracle
2.enhancementEnabled of Mybatis
环境
1. Java HotSpot(TM) Server VM (build 1.5.0_12-b04, mixed mode)
Java HotSpot(TM) Server VM (build 1.6.0_05-b13, mixed mode)
2. Intel(R) Core(TM)2 CPU T7400 @ 2.16GHz L2 4M
3. JVM OPTION -Xms512m -Xmx1024m -XX:PermSize=96m
从数据库中读取10000行, 5列数据情况, Java Bean对象大约不到100个属性。循环20次, 外加5次的赃数据。
A. defaultRowPrefetch=default enhancementEnabled=false/true 754ms/743ms
B. defaultRowPrefetch=50 enhancementEnabled=false/true 389ms/382ms
C. defaultRowPrefetch=100 enhancementEnabled=false/true 319ms/319ms
D. defaultRowPrefetch=200 enhancementEnabled=false/true 277ms/274ms
E. defaultRowPrefetch=500 enhancementEnabled=false/true 251ms/250ms
F. defaultRowPrefetch=1000 enhancementEnabled=false/true 242ms/238ms
G. defaultRowPrefetch=1000 enhancementEnabled=true 237ms(JAVA6)
H. defaultRowPrefetch=200 enhancementEnabled=true 271MS(JAVA6)

总结以上情况, 在数据行比较多的情况下, defaultRowPrefetch值的提高, 对于性能的影响是显著的, 但是, 这个提升是牺牲很多内存为代价的, 因此, 如果过高的defaultRowPrefetch值会导致内存比较紧张。 另外值得说明的是, 在一样的参数前提下, JAVA6对于性能还是有一定的提升的。对于比较大的查询, defaultRowPrefetch经验值应该是200还是合理的。 另外, 对于enhancementEnabled选项带来的收益, 相对来说比较少。 但是,对于高压力的系统, 这是无IO等待下情况的代码执行提高这些是非常值。

以上的测试数据列数比较少, 因此在JAVA BEAN的建立上是非常的节约时间的, 我们看看在差不多100个属性的填充下的性能表现, 我们已经知道了defaultRowPrefetch带来收益的经验值。 因此, 我们设置defaultRowPrefetch=200.
A. defaultRowPrefetch=200 enhancementEnabled=false 1736ms
B. defaultRowPrefetch=200 enhancementEnabled=true 1721ms
C. defaultRowPrefetch=50 enhancementEnabled=true 1866ms

OK
enhancementEnabled继续表明对性能的提升作用很小, 但是列的数据大小对性能的影响是非常大的。 但是, 我们无法确定这个时间是消耗在Java Bean 填充上 还是列读取上。Mybatis没有具体的办法测试。 不过, 在减少结果参数说明的情况下, 性能能得到明显的提升, 我们还是可以断定, JAVA BEAN的被声明成结果映射的时候, 尽量减少结果映射的列,可以获得很高性能的提升。 因此, 使用Mybatis操作大量的数据的表, 建议只映射应该获取到的数据, 而不是全部的列。 select * from db where... 你可以取需要的列到java bean. 总而言之: select * from db where... 这样的形式对性能影响比 把所有的列映射到Java Bean 来的小! set bean property + ResultSet.getXXX(int index)的操作消耗了大部分的性能。


一些代码片段:
数据原的定义
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass">
<value>oracle.jdbc.OracleDriver</value>
</property>
<property name="jdbcUrl">
<value>jdbc:oracle:thin:@10.0.0.1:1521:test</value>
</property>
<property name="properties">
<props>
<prop key="user">test</prop>
<prop key="password">test</prop>
<prop key="defaultRowPrefetch">50</prop>
</props>
</property>
</bean>

为单个SQL查询定义defaultRowPrefetch, Mybatis的定义中为fetchSize
<select id="MS-FIND-PublishedOffers-By-MemberId-Paged" resultMap="RM-OfferResult" fetchSize="200">

CGLIB
增强定义
<settings cacheModelsEnabled="true" enhancementEnabled="true" lazyLoadingEnabled="false" maxRequests="3000" maxSessions="3000" maxTransactions="3000" useStatementNamespaces="false"/>

 

 

 

根据Ibatis手册上配置参数说明:

参数名称

参数说明

cacheModelsEnabled

是否启动ibatis中的缓存功能。

enhancementEnabled

是否需要POJO启动Java字节码增强功能,可以提升getter/setter的调用效能避免Java反射所带来的性能开销。

lazyLoadingEnabled

是否同时Lazy Loading带来极大的性能提升。

useStatementNamespaces

是否使用 domain xml 文件中 namespace 别名配置。

maxRequests

最大并发请求数(Statemetn)

maxTransactions

最大并发事务数

maxSessions

最大Session数,当前最大允许的并发 SqlMapCliect

maxSessions

须界于 maxTransactionsmaxRequests之间进行配置

根据自己的多次实践证明,发现这些配置参数的选择与数值将对系统的影响是很大的。

经过多次摸索,按照以下配置参数进行配置可以将ibatis的性能进行提升。仅供参数,还需要根据您自己的实 际情况来界定。

具体配置参数如下:

<sqlMapConfig>

<settings cacheModelsEnabled="true"

lazyLoadingEnabled="true"

enhancementEnabled="true"

errorTracingEnabled="true"

maxSessions="1024"

maxTransactions="512"

maxRequests="2048"

useStatementNamespaces="true" />

分享到:
评论
2 楼 DEMONU 2014-04-30  
1 楼 DEMONU 2014-04-30  
NB的文章,3gods.com

相关推荐

    Mybatis优化

    ### Mybatis优化技巧详解 #### 一、引言 MyBatis是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集的过程。通过XML或注解的方式将要...

    mybatis 对clob类型转换

    总结,处理MyBatis中的CLOB类型转换,主要涉及自定义TypeHandler、配置MyBatis、在Mapper中应用TypeHandler,以及在编程时考虑异常处理和性能优化。通过这些步骤,可以有效地管理和操作CLOB类型数据,解决插入数据库...

    从iBatis迁移到MyBatis

    iBatis是一个Java语言中的SQL映射框架,而MyBatis是在iBatis的基础上发展起来的,提供了更多的功能和优化。 在数据库开发中,持久层框架是至关重要的,它负责处理数据库的CRUD(创建、读取、更新、删除)操作,以及...

    mybatis一对多性能优化demo

    本Demo将重点探讨MyBatis中一对多性能优化的策略。 首先,我们来看一下MyBatis如何配置一对多映射。在`mybatis-config.xml`或Mapper XML文件中,我们通常会定义`&lt;association&gt;`标签来描述一对一的关系,而对于一对...

    学习手册 “玩转”Java系列 — Mybatis

    《玩转》Java系列之Mybatis学习手册,旨在帮助开发者深入理解并熟练运用Mybatis这一流行持久层框架。本手册将全面解析Mybatis的核心概念、关键功能及其在实际开发中的应用,助你从初学者晋升为Mybatis高手。 1. **...

    mybatis查询分页插件

    实现原理为mybatis的拦截器,但是比网上目前流行的修行sql方式优化,只是第一次调用查询时需要处理,以后不需要再额外处理。 生成的sql为自动化的最优(基于数据绑定方式的sql)。 缺点: 扩展需要对mybatis源码...

    针对mybatis3 基本环境搭建优化(一) .

    在本教程中,我们将深入探讨如何搭建 MyBatis 3 的基本环境,并进行一些优化,包括添加别名和查询优化。 一、MyBatis 环境搭建 1. **依赖引入**:在构建项目时,首先需要在你的项目中添加 MyBatis 的依赖。如果你...

    mybatis的oracle的批量插入优化和mybatis的generator自动生成三层文件

    本文将详细探讨如何在Oracle数据库中进行批量插入优化,并介绍MyBatis Generator这一自动化代码生成工具,以提高开发效率。 首先,让我们深入理解Oracle数据库中的批量插入。批量插入可以显著提升性能,尤其是在...

    对mybatis3 基本环境搭建优化(二)

    在对MyBatis3的基本环境搭建进行优化的过程中,我们需要了解并掌握一系列的关键步骤和技术要点。在本篇中,我们将深入探讨MyBatis3的核心概念、配置优化以及开发实践中的最佳实践,以帮助开发者构建高效、稳定的开发...

    mybatis 2.7 sql优化破解版

    mybatis 2.7 sql优化破解版,在mybatis 2.7 破解版的基础上进行了部分优化,具体为会在生成的xml文件中,将字段名使用反引号引起来

    mybatis逆向工具generator,中文注释,Byte改Integer

    总的来说,这个定制版的MyBatis Generator不仅提供了中文注释以增强可读性,还优化了默认的类型转换,使得生成的代码更符合实际开发需求,特别是在处理可能超出`Byte`范围的整数字段时。通过理解这个工具的特点和...

    spring Boot与Mybatis整合优化详解

    Spring Boot与Mybatis整合优化详解 在本文中,我们将详细介绍Spring Boot与Mybatis整合优化的相关知识点。 一、取消spring-mybatis.xml配置 在传统的Mybatis-Spring整合中,我们需要在spring-mybatis.xml中配置...

    mybatis-generator(mybatis逆向工程超级优化版)

    这款"mybatis-generator(mybatis逆向工程超级优化版)"是原版基础上进行了一系列优化,以满足更加高效、便捷的开发需求。 首先,优化点之一在于将Mapper接口的后缀由默认的`Mapper`改为了`Dao`。这种改动符合Java...

    mybatis-3-mybatis-3.2.6

    通过对MyBatis 3.2.6源码的学习,开发者可以更好地理解其工作原理,从而优化性能、解决问题,甚至进行扩展和定制。例如,你可以深入了解Executor的执行策略,调整批处理的粒度;或者研究TypeHandler,针对特定类型...

    14 mybatis转钱和查询余额(优化后)

    在这个“14 mybatis转钱和查询余额(优化后)”的主题中,我们主要探讨的是如何在MyBatis中进行资金转账操作以及优化查询余额的性能。 首先,转账操作通常涉及到两个关键步骤:扣除原账户金额和增加目标账户金额。在...

    Mybatis Generator将tinyint映射成Integer的解决办法.pdf

    在使用MyBatis Generator生成Java ...理解这种类型的转换规则以及如何自定义映射关系,对优化MyBatis的使用和提高代码的可维护性至关重要。在实际开发中,应根据项目的具体需求和数据库设计来选择合适的方法进行处理。

    MyBatis 官方笔记 + MyBatis 3.5.10 官方英文文档

    在 MyBatis 3.5.10 版本中,我们能够看到许多优化和改进,使得开发更为便捷和高效。下面将详细探讨 MyBatis 的核心概念和功能,以及 3.5.10 版本的特性。 1. **配置与环境搭建** - **mybatis-config.xml**:...

    mybatisx.zip

    这个压缩包文件“mybatisx.zip”包含了多个版本的MybatisX插件,包括MybatisX-1.4.16.zip、MybatisX-1.4.8.zip、MybatisX-1.4.6.zip以及MybatisX-1.1.2.zip。这些版本的差异可能体现在功能增强、性能优化或者修复...

    mybatis_plugin 2.92

    "mybatis_plugin 2.92" 可能是一个为 MyBatis 添加特定功能或优化的第三方插件集合,通过合理使用这些插件,可以提高开发效率,优化应用程序的性能,或者简化某些复杂的数据库操作。在实际项目中,根据需求选择和...

    mybatis-platform_mybatis_

    通过MyBatis,我们可以将SQL语句与Java代码解耦,提高代码的可读性和可维护性,而Druid则是一个强大的数据库连接池,它提供了监控、统计以及SQL优化等功能,能够提升系统的稳定性和性能。" 【知识点详解】: 1. **...

Global site tag (gtag.js) - Google Analytics