海量数据迁移之分区表批量insert性能改进

在平时的工作中接触到的分区表一般都比较大,而且分区也少则几十,多则几百,上千。
在数据迁移的时候,分区表的迁移更是块大骨头,因为数据量太大,而且有些分区表中还有一些lob字段,想直接通过sqlldr来迁移还是需要做一些额外的工作。
如果通过datapump分区导出数据,批量导入,也是一种思路,不过需要考虑好并发的进程。
通过oracle_datapump来做数据的导入,可能更为灵活,但是不是绝对的。最近就做了一些相关的数据导入测试,感触不少。

比如,目前我们需要导入的两个大表,一个是memo,一个是charge,分区都有200多个。
而且数据分布不是很均匀。有的分区可能数据要多很多。使用oracle_datapump抽取的时候,比如memo表有25G,如果按照100M为一个单位,那么就要生成250个dump 文件。每个dump文件中大概有50多万条数据,抽取的dump文件不是基于分区的。然后在目标库中以外部表的形式加载,然后使用insert来做数据插入,启用8个并行度。导入的时候速度就不是很理想。平均每个dump文件需要大约1~2分钟的时间,甚至更长。就算减少并行度,控制在4左右,速度还是没有什么变化。
本来冥思苦想的这个方案性能打了折扣,然后再一次尝试,限制生成的dump文件个数,比如memo表有25G,生成80个dump,这样每个dump文件就有将近300M左右。这样每个dump文件就大概由150万的数据。还是启用了同样的并行,速度就会快很多,一个dump文件大约在1~2分钟,dump的个数少了大半,时间就随之节省了很多。

基于这个问题,我的想法是dump在100M左右的时候,启用并行不会有什么大的起色,启用8个4个,应该和不启用并行效果是类似的。
如果dump文件大了很多,如果启用并行,就会有相应的进程能够合理的处理一部分数据。
同时,因为memo表是分区表,如果做insert插入的时候,一个insert会在每个分区上加一个锁,这样就是200个多锁,这个也是很消耗资源的。如果频繁的做插入,commit动作,就会不断的去加同样数量级的锁,无形中也快拖累加载速度。如果dump文件较大,还是会加同样的锁,但是会在一定程度上使得并行使用的更为充分。可能加锁的频率降低了,对系统的负载也会小很多。

如果想有较大的改进的话,我的个人想法就是通过分区级别导出数据,然后在数据插入的时候,也是基于分区导入,这样就可以同时做多个insert操作,而且每个insert只会锁定一个相应的分区。而且考虑加入并行,可能性会好很多。
按照这个思路,就没有严格意义上的大表了,我们都可以切分再切分。

时间: 2024-07-30 10:57:04

海量数据迁移之分区表批量insert性能改进的相关文章

Mysql 批量insert 性能测试

批量执行insert时,有多种执行方式: 1.循环单条执行,类似: for(){ insert(sql); } 2.合并为一个事务执行(注:Mysql默认事务是自动提交的,需关闭事务自动提交),类似: 事务begin for() { insert(sql); } 事务commit 3.采用insert...values value1,value2批量执行,类似: insert into table_name values (value1),(value2)...(valueN); 下表是在单机情

海量数据迁移之一个误操作的问题总结

在生产环境中的数据迁移还是很惊心动魄的,毕竟生产的数据不容许有任何潜在的问题,很小的问题也可能导致业务的终端,这个时候dba的角色是很重要的,如果dba犯了一个很细小的问题,在海量数据迁移中可能会导致灾难性的结果,所以今天和大家讨论一下关于由vi误操作导致的问题及总结. 结合今天早上的例子来说明. 目前生产环境已经有大量的用户数据了,需要从老系统迁移一批用户数据过来,一切都在安装好计划进行准备和操作.我是采用了外部表的方式,把一个很大的表分为了几十上百个外部表,采用insert方式加载的. 数据

在DB2中提高INSERT性能的技巧(1)_DB2

正在看的db2教程是:在DB2中提高INSERT性能的技巧(1).INSERT 处理过程概述 首先让我们快速地看看插入一行时的处理步骤.这些步骤中的每一步都有优化的潜力,对此我们在后面会一一讨论. 在客户机准备 语句.对于动态 SQL,在语句执行前就要做这一步,此处的性能是很重要的:对于静态 SQL,这一步的性能实际上关系不大,因为语句的准备是事先完成的. 在客户机,将要插入的行的各个 列值组装起来,发送到 DB2 服务器. DB2 服务器确定将这一行插入到哪一页中. DB2 在 用于该页的缓冲

select-mybatis加oracle批量insert中的序列问题,可不可以用union做批量的sql语句--急

问题描述 mybatis加oracle批量insert中的序列问题,可不可以用union做批量的sql语句--急 <insert id="saveManyPopInfo" parameterType="java.util.List"> insert into popinfo (popid,popname,remark) select seq_popid.nextval,p.* from ( <foreach collection="lis

如何让redis 迁移大key的restore性能提升6倍

redis支持migrate key的命令,支持从源redis节点迁移key到目标节点上,目标节点再执行restore命令,将数据加载进内存中.以800MB,数据类型为zset(skiplist) 的 key为例,测试环境为本地开发机上两台redis,忽略网络的影响.原生的redis 在restore时执行需要163s,优化后的redis执行需要27s. 1. 原生redis restore的性能瓶颈 通过扁鹊工具分析,可以看到cpu的运行情况如下: 查看源码可知,migrate 遍历出来的zs

MySQL内核月报 2015.01-MySQL · 优化改进· 复制性能改进过程

前言 与oracle 不同,mysql 的主库与备库的同步是通过 binlog 实现的,而redo日志只做为mysql 实例的crash recovery使用.mysql在4.x 的时候放弃redo 的同步策略而引入 binlog的同步,一个重要原因是为了兼容其它非事务存储引擎,否则主备同步是没有办法进行的. redo 日志同步属于物理同步方法,简单直接,将修改的物理部分传送到备库执行,主备共用一致的 LSN,只要保证 LSN 相同即可,同一时刻,只能主库或备库一方接受写请求: binlog的同

一个60亿数据表改分区表+数据清理的改进思路

今天有个同学问我一个问题,也是一个实际的案例,我简单分析了一下,发现还是有很多可以考究的地方.仅做参考. 问题是,系统里目前有一个大表,因为历史数据的沉淀,目前有60多亿的数据,不是分区表,现在得到反馈说insert的操作比较满,想优化一下,同时把部分历史数据需要做一些清理. 对于这类操作,要求停机时间尽可能短,有什么好的办法. 对于这个问题看起来问题似乎是很明显的. 目前反应出的问题是Insert慢,可能有下面的几个原因. 1.表索引巨大,索引维护管理要复杂一些 2.表中可能含有一些冗余索引,

分区表的一个持续改进方案

今天看到一个同事发了一封邮件,是关于分区的,他说目前某个表的分区需要添加,为了保险起见,让我先添加三年的.这里折射出几个问题. 1.如果没有这位开发同学提醒,我还真不知道哪个表的分区数据会有问题 2.添加三年的分区,这个对于DBA来说是一个体力活,哪怕写脚本也是,本身维护起来就比较纠结. 3.三年后的分区谁来维护,我不敢拍着胸脯说我来,我想开发的同学也不会很肯定能够记住这件事情. 4.历史数据的清理,在这方面来看,如果没有业务的确认,DBA清理就无从谈起,如果都不确定,就是按兵不动.这是分区的优

MySQL 5.6.12的Innodb性能改进

简单的记录下,在MySQL5.6.12中innodb层的3点跟性能相关的改进 1.在文件操作部分,移除了许多sleep操作,而是改用condition wait 对应的bug http://bugs.mysql.com/bug.php?id=68588. 在Mark的测试中,有近一倍的性能提升 http://bazaar.launchpad.net/~mysql/mysql-server/5.6/revision/4981 主要修改都几种在函数fil_flush中: 每个文件结构体node都增加