10.10.6  大数据量插入优化

在很多涉及支付和金融相关的系统中,夜间会进行批处理,在批处理的一开始或最后一般需要将数据回库,因为应用和数据库通常部署在不同的服务器,而且应用所在的服务器一般也不会去安装oracle客户端,同时为了应用管理和开发模式统一,很多会利用mybatis的foreach collection特性,如下:

<insert id="batchInsertStudent" parameterType="List">

insert into /*+ append_values */ t_student(id,name)

<foreach collection="list" item="item" index="index" separator="union all">

select #{item.id}, #{item.name} from dual

</foreach>

</insert>

还有一些开发人员会仿照mysql的写法,拼接成一个巨大的SQL,一次性提交给oracle执行,如下:

这些写法会生成很长的SQL语句,严重浪费客户端内存和oracle服务器共享池,如果这段期间需要生成AWR报告的话,没有这些语句几十秒就完成了,有这些语句的时候可能要十几分钟,生成的AWR文件就有十几兆,并且oracle服务器CPU利用率一直高负载。如果仅仅是如此也就罢了,最主要是这些看似优化的方法实际上性能仅仅比一条条提交提升快了几倍而已,对于一次性加载几十万、几百万行来说,并没有采用真正高效的做法。对于此类需要加载大量数据的方法,如本书第7章所述,应尽可能采用特殊优化的接口而不是为通用CRUD目的实现的接口,比如mybatis提供了批量执行器ExecutorType.BATCH,JDBC也提供了标准的批处理接口。

mybatis批量执行器的实现如下:

<insert id="insertBatch" parameterType="chapter10.batch.pojo.User">

insert into EMP (EMPNO,ENAME,JOB,MGR,SAL,COMM,DEPTNO)

values (#{empno,jdbcType=BIGINT},……,#{deptno,jdbcType=BIGINT})

</insert>

SqlSession session2 = sqlMapper.openSession(ExecutorType.BATCH, false);// 批处理方式 手动提交事务

UserMapper userDao2 = session2.getMapper(UserMapper.class);

try {

long t1 = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

User user_new = new User();

user_new.setComm(i % 10000);

……

user_new.setSal(i % 1000);

userDao2.insertBatch(user_new);

if (i % 10000 == 0) {

session2.commit();

}

}

System.out.println(System.currentTimeMillis() - t1 + "ms");

} finally {

session2.commit();

session2.close();

}

oracle jdbc批处理的实现如下:

Connection connection = dbpool.getConnection();

connection.setAutoCommit(false);

PreparedStatement preparedStatement = connection.prepareStatement("insert into EMP (EMPNO,ENAME,JOB,MGR,SAL,COMM,DEPTNO) values (?,?,?,?,?,?,?)");

long t1 = System.currentTimeMillis();

for (int i = 0; i < 1000000; i++) {

User user_new = new User();

user_new.setComm(i % 10000);

……

preparedStatement.setInt(7, user_new.getDeptno());

preparedStatement.addBatch();

if (i % 10000 == 0) {

preparedStatement.executeBatch();

connection.commit();

}

}

preparedStatement.close();

加载100w数据,使用jdbc Batch需要3秒左右,mybatis batch(标准JDBC批处理)9.2秒,mybatis foreach每5000条(1w时报java.sql.SQLException: ORA-01745: 无效的主机/绑定变量名)提交一次,需要执行203秒左右,甚至不如每行一次、每10000行提交一次的效率,并且子游标的共享内存占用了27M,固定内存加起来占了14M左右,如下:

SQL> select o.sql_id, sharable_mem, persistent_mem, runtime_mem

2    from v$sql o

3   where o.sql_text like '%insert into EMP (%'

4     and sql_text not like '%v$sql%'

5  ;

SQL_ID        SHARABLE_MEM PERSISTENT_MEM RUNTIME_MEM

------------- ------------ -------------- -----------

bqwhad7f0gxxd     27473066        9127256     4925984

mysql/oracle jdbc大数据量插入优化的更多相关文章

  1. C# & SQL Server大数据量插入方式对比

    以下内容大部分来自: http://blog.csdn.net/tjvictor/article/details/4360030 部分内容出自互联网,实验结果为亲测. 最近自己开发一个向数据库中插入大 ...

  2. MySQL分页查询大数据量优化方法

    方法1: 直接使用数据库提供的SQL语句 语句样式: MySQL中,可用如下方法: SELECT * FROM 表名称 LIMIT M,N适应场景: 适用于数据量较少的情况(元组百/千级)原因/缺点: ...

  3. MySQL数据库解决大数据量存储问题

    转载自:https://www.cnblogs.com/ryanzheng/p/8334915.html 提问:如何设计或优化千万级别的大表?此外无其他信息,个人觉得这个话题有点范,就只好简单说下该如 ...

  4. mysql innobackupex xtrabackup 大数据量 备份 还原

    大数据量备份与还原,始终是个难点.当MYSQL超10G,用mysqldump来导出就比较慢了.在这里推荐xtrabackup,这个工具比mysqldump要快很多. 一.Xtrabackup介绍 1, ...

  5. mysql innobackupex xtrabackup 大数据量 备份 还原(转)

    原文:http://blog.51yip.com/mysql/1650.html 作者:海底苍鹰 大数据量备份与还原,始终是个难点.当MYSQL超10G,用mysqldump来导出就比较慢了.在这里推 ...

  6. Mysql千万级大数据量查询优化

    来源于:https://blog.csdn.net/A350204530/article/details/79040277 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 ord ...

  7. sql server 2005 大数据量插入性能对比

    sql server 2005大数据量的插入操作 第一,写个存储过程,传入参数,存储过程里面是insert操作, 第二,用System.Data.SqlClient.SqlBulkCopy实例方法, ...

  8. MYSQL数据库导入大数据量sql文件失败的解决方案

    1.在讨论这个问题之前首先介绍一下什么是"大数据量sql文件". 导出sql文件.选择数据库-----右击选择"转储SQL文件"-----选择"结构和 ...

  9. SQL优化-大数据量分页优化

    百万数据量SQL,在进行分页查询时会出现性能问题,例如我们使用PageHelper时,由于分页查询时,PageHelper会拦截查询的语句会进行两个步骤 1.添加 select count(*)fro ...

随机推荐

  1. Pytorch快速入门及在线体验

    本文搭配了Pytorch在线环境,可以直接在线体验. Pytorch是Facebook 的 AI 研究团队发布了一个基于 Python的科学计算包,旨在服务两类场合: 1.替代numpy发挥GPU潜能 ...

  2. MJExtension代码解释

    Runtime 是什么? objective-C会把函数调用的转换为消息发送,objc_MsgSend(receiver, msg), 注意,recevier指的是消息的接受者.那么self, sup ...

  3. react 使用 redux 的时候 用 ref获取子组件的state

    由于 redux是无状态的,所以当我们在子组件中使用了 redux的时候,再父组件中,使用  ref 来获取子组件的state时,发现为一个空对象. 其实这个是有解决方案法的,原因在于 我们使用的 r ...

  4. Go vs Erlang - 转

    From http://zhang.hu/go-vs-erlang/ Go vs Erlang 因为 云巴 系统对高并发.低延迟的需求,我们对各个语言.平台做了很多的调研比较工作.这自然就包括致力于开 ...

  5. time_t time()

    time_t  atime,  btime; time(&atime); btime = time(0); 两种方式效果一样.

  6. LeetCode69.x的平方根

    实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 输出: 2 示例 ...

  7. 获取Sqlserver上一句语句执行后受影响的行数@@rowCount

    from:http://blog.163.com/rihui_7/blog/static/212285143201381343240404/ 返回受上一语句影响的行数. ROWCOUNT_BIG.&q ...

  8. 一个获取本机ip地址的正则

    ifconfig|grep -oP '(?<=inet addr:)(?=(?!127\.0\.0\.1))\d+(\.\d+){3}'

  9. 原生JS实现addClass,removeClass,toggleClass

    jQuery操作class的方式非常强大,但是目前还有一些人不知道如何使用或者由于项目统一性的原因无法使用jquery. 在此写了一个利用原生js来实现对dom元素class的操作方法 1.addCl ...

  10. ueditor上传图片配置成功,但是如何删除无用的图片

    我使用ueditor作为富文本编辑器,配置已经好了,上传功能也好了.现在的问题是当使用ueditor上传图片的时候,选择了图片就立刻上传到指定的文件夹里,而后续即使没有保存该篇文章内容,即取消操作,图 ...