Mybatis 大数据量的批量insert解决方案
来源:互联网 发布:高优门禁 软件 编辑:程序博客网 时间:2024/05/06 21:28
http://blog.csdn.net/wlwlwlwl015/article/details/50246717
版权声明:本文为博主原创文章,转载请标明出处(http://blog.csdn.net/wlwlwlwl015)Thanks.
目录(?)[+]
前言
通过Mybatis做7000+数据量的批量插入的时候报错了,error log如下:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
可以看到这种异常无法捕捉,仅能看到异常指向了druid和ibatis的原码处,初步猜测是由于默认的SqlSession无法支持这个数量级的批量操作,下面就结合源码和官方文档具体看一看。
源码分析
项目使用的是Spring+Mybatis,在Dao层是通过Spring提供的SqlSessionTemplate来获取SqlSession的:
@Resource(name = "sqlSessionTemplate")private SqlSessionTemplate sqlSessionTemplate;public SqlSessionTemplate getSqlSessionTemplate() { return sqlSessionTemplate;}
为了验证,接下看一下它是如何提供SqlSesion的,打开SqlSessionTemplate的源码,看一下它的构造方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
接下来再点开getDefaultExecutorType这个方法:
- 1
- 2
- 3
可以看到它直接返回了类中的全局变量defaultExecutorType
,我们再在类的头部寻找一下这个变量:
- 1
找到了,Spring为我们提供的默认执行器类型为Simple,它的类型一共有三种:
- 1
- 2
- 3
- 4
- 5
- 6
仔细观察一下,发现有3个枚举类型,其中有一个BATCH是否和批量操作有关呢?我们看一下mybatis官方文档中对这三个值的描述:
- ExecutorType.SIMPLE: 这个执行器类型不做特殊的事情。它为每个语句的执行创建一个新的预处理语句。
- ExecutorType.REUSE: 这个执行器类型会复用预处理语句。
- ExecutorType.BATCH:这个执行器会批量执行所有更新语句,如果 SELECT 在它们中间执行还会标定它们是 必须的,来保证一个简单并易于理解的行为。
可以看到我的使用的SIMPLE会为每个语句创建一个新的预处理语句,也就是创建一个PreparedStatement对象,即便我们使用druid连接池进行处理,依然是每次都会向池中put一次并加入druid的cache中。这个效率可想而知,所以那个异常也有可能是insert timeout导致等待时间超过数据库驱动的最大等待值。
好了,已解决问题为主,根据分析我们选择通过BATCH
的方式来创建SqlSession,官方也提供了一系列重载方法:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
可以观察到主要有四种参数类型,分别是
- Connection connection
- ExecutorType execType
- TransactionIsolationLevel level
- boolean autoCommit
官方文档中对这些参数也有详细的解释:
SqlSessionFactory 有六个方法可以用来创建 SqlSession 实例。通常来说,如何决定是你 选择下面这些方法时:
Transaction (事务): 你想为 session 使用事务或者使用自动提交(通常意味着很多 数据库和/或 JDBC 驱动没有事务)?
Connection (连接): 你想 MyBatis 获得来自配置的数据源的连接还是提供你自己
Execution (执行): 你想 MyBatis 复用预处理语句和/或批量更新语句(包括插入和 删除)?
所以根据需求选择即可,由于我们要做的事情是批量insert,所以我们选择SqlSession openSession(ExecutorType execType, boolean autoCommit)
顺带一提关于TransactionIsolationLevel也就是我们经常提起的事务隔离级别,官方文档中也介绍的很到位:
MyBatis 为事务隔离级别调用使用一个 Java 枚举包装器, 称为 TransactionIsolationLevel,
否则它们按预期的方式来工作,并有 JDBC 支持的 5 级 (
NONE,
READ_UNCOMMITTED
READ_COMMITTED,
REPEATABLE_READ,
SERIALIZA BLE)
解决问题
回归正题,初步找到了问题原因,那我们换一中SqlSession的获取方式再试试看。
testing… 2minutes later…
不幸的是,依旧报相同的错误,看来不仅仅是ExecutorType的问题,那会不会是一次commit的数据量过大导致响应时间过长呢?上面我也提到了这种可能性,那么就再分批次处理试试,也就是说,在同一事务范围内,分批commit insert batch。具体看一下Dao层的代码实现:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
再次测试,程序没有报异常,总共7728条数据 insert的时间大约为10s左右,如下图所示,
总结
简单记录一下Mybatis批量insert大数据量数据的解决方案,仅供参考,Tne End。
- Mybatis 大数据量的批量insert解决方案
- Mybatis 大数据量的批量insert解决方案
- Mybatis 大数据量的批量insert解决方案
- Mybatis 大数据量的批量insert解决方案
- MySQL大数据量insert的优化
- oracle insert 大数据量的经验
- mybatis批量insert的mapper xml写法
- EXCEL大数据量导出的解决方案
- WEB网站大数据量的性能解决方案
- WEB网站大数据量的性能解决方案
- EXCEL大数据量导出的解决方案
- EXCEL大数据量导出的解决方案
- echarts大数据量展示的解决方案
- Oracle insert大数据量经验之谈
- mybatis 批量insert
- mybatis 批量insert
- Mybatis 批量insert
- mybatis 批量insert,update
- 【Mybatis】一对一,一对多,多对多映射
- 【笔记】B-树和B+树
- 【我的Java笔记】File类
- JRI方式实现Java和R连接--关键点在配置环境变量,重启Eclipse
- BZOJ 1491 [NOI2007]社交网络(floyd)
- Mybatis 大数据量的批量insert解决方案
- Python3与OpenCV3.3 图像处理(五)--图像运算
- G
- Emptying the Baltic
- 插入排序:直接插入, 折半插入,希尔插入
- 码农日常工具推荐
- 汇编实验
- mysql的sql执行计划详解(非常有用)
- odoo10打印预览功能