海量数据迁移之外部表并行抽取

在10g开始的新特性中,外部表是一个不容忽视的好工具。对于大型项目中海量数据使用sqlloader是一种全新的方式,不过很明显,sqlloader的可扩展性更强,但是基于oracle平台的数据迁移来说,外部表的性能也不错。对于数据迁移来说也是一个很好的方案。
使用外部表来做数据迁移,可以“动态”加载数据,能够很方便的从数据库中加载数据,对于数据校验来说就显得很有优势了,而对于sqlloader来说,可能得等到数据加载的时候才知道是不是有问题,如果对于数据的准确性要求极高,可以使用外部表动态加载数据到备库,和现有的数据做比对,减少在升级过程中带来的灾难。
还有关于数据类型,对于clob,blob的加载,大家都比较头疼,在sqlloader中可能需要做一些额外的工作,来外部表中就和操作普通的表没有什么区别。

先来说说数据抽取的部分。
一下是我今天完成的部分脚本,目录结构如下。
drwxr-xr-x 2 ora11g dba 4096 Jun  9 22:14 DUMP_LIST
drwxr-xr-x 2 ora11g dba 4096 Jun  9 23:25 extract
drwxr-xr-x 2 ora11g dba 4096 Jun  9 22:32 parfile
[ora11g@rac1 ext_datapump]$ pwd
/u01/ora11g/test/ext_datapump

对于一些比较大的表,如果占用的空间在好几十个G左右的时候,生成一个巨大的dump文件就有问题了,一来是关于io,顺序的写入dump文件,而且在加载的时候也没有其他的选择了,只能从头到尾一步一步来。
我的设想就是如果一个表有100G,可以把他切分为200个dump文件,每个500M,或者说生成1000个dump文件,每个dump文件100M,这样在加载的时候就可以很清楚的看到目前数据加载的进度了。
我使用了如下的脚本来生成多个dump文件,
tablst=`cat ../parfile/tablst|awk '{print "'\''" $1 "'\'',"}'`
#for segment within 50M, will use parallel 1, and parallel will calculated with segment_bytes_size_MB/50M
page=50
sqlplus -s n1/n1
set feedback off
set head off
set line 100
set pages 0
set long 10000
set termout off
col segment_name for a40
col parallel format 9999
spool tab_parall_temp.lst
select distinct segment_name,ceil(sum(bytes/1024/1024)/50) parallel from user_segments
where segment_name in (select table_name from user_tables where table_name in ($tablst'x') and table_name not in (select table_name from user_external_tables))
group by segment_name order by 2 desc;
spool off;
EOF
sed  '/^$/d' tab_parall_temp.lst |sort > ../parfile/tab_parall.lst
rm tab_parall_temp.lst

运行脚本后,结果如下所示。
BIG_INSERT                                      1                                                   
CLOB_TEST                                       1                                                   
SMALL_INSERT                                    1                                                   
T                                               1                                                   
TEMP_TEST                                       1                                                   
TEST                                            1                                                   
TEST_DATA                                       1                                                   
TT                                              2                                                   
T_TEMP                                          1 
可以看到表tt比较大,就需要分成了两个dump。加载的时候也可以分批加载。
当然,生成的dump的个数也和一个数据库参数密切相关,像我目前的库,最大的并行只有30. 意味着如果我要把一个表切分成50个dump,根据配置,只能最多切分为30个。
parallel_max_servers                 integer     30

在生面的基础上,可以采用下面的脚本来生成dump文件。
#### source owner $1
#### tab_name $2
#### target owner $3
#### dump directory $4

owner=`echo "$1"|tr '[a-z]' '[A-Z]'`
tab_name=`echo "$2"|tr '[a-z]' '[A-Z]'`
tablst=`cat ../parfile/tablst|awk '{print "'\''" $1 "'\'',"}'`

tmp_parallel=`grep -w $tab_name ../parfile/tab_parall.lst|awk '{print $2}'`
for i in {1..$tmp_parallel};
do
echo \'${tab_name}_$i.dmp\', >> tmp_${tab_name}_par_dmp.lst
done

sed -e '/^$/d' -e '$s/.$//' tmp_${tab_name}_par_dmp.lst > ../DUMP_LIST/${tab_name}_par_dmp.lst
dump_list=`cat ../DUMP_LIST/${tab_name}_par_dmp.lst`
#echo $dump_list
#echo $tmp_parallel
sqlplus -s n1/n1
set serveroutput on
DECLARE
TABLE_FLAG number(2);
begin
execute immediate 'select count(*) from all_tables where owner=upper(''$1'') and table_name=upper(''$2'')' into table_flag;
if(table_flag>0) then 
dbms_output.put_line( 'TABLE '||'$tab_name'||' exists in owner account,proceed...');
else 
dbms_output.put_line( 'TABLE does not exists in owner account,please check again');
return;
end if;
end;
/

set timing on
DECLARE
TABLE_FLAG number(2);
begin
execute immediate 'select count(*) from all_external_tables where owner=upper(''$3'') and table_name=upper(''$2'')' into table_flag;
if(table_flag>0) then 
dbms_output.put_line( 'External table exists in owner account,proceed...');
execute immediate 'drop table $3.$2_ext';
end if;
end;
/
exec dbms_output.put_line('Get Dump file for $1.$2...');
create table $3.$2_ext
    ORGANIZATION EXTERNAL
    (TYPE ORACLE_DATAPUMP
     DEFAULT DIRECTORY $4 
     LOCATION (
     $dump_list
    )
    )
    parallel $tmp_parallel 
    as
    select /*+ parallel(t $tmp_parallel) */ * from $1.$2 t;
set feedback off;
set timing off
drop table $3.$2_ext;
EOF
rm tmp_${tab_name}_par_dmp.lst 
exit

脚本运行效果如下:
Get Dump file for n1.TT...
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
Table created.
Elapsed: 00:00:03.07
TABLE T_TEMP exists in owner account,proceed...
PL/SQL procedure successfully completed.
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.01
Get Dump file for n1.T_TEMP...
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.00
Table created.
Elapsed: 00:00:01.39

生成的dump文件如下:
[ora11g@rac1 expdp]$ ll *.dmp
-rw-r----- 1 ora11g dba   466944 Jun 10 01:43 BIG_INSERT_1.dmp
-rw-r----- 1 ora11g dba    12288 Jun 10 01:43 CLOB_TEST_1.dmp
-rw-r----- 1 ora11g dba    40960 Jun 10 01:43 SMALL_INSERT_1.dmp
-rw-r----- 1 ora11g dba 30531584 Jun 10 01:43 T_1.dmp
-rw-r----- 1 ora11g dba   524288 Jun 10 01:43 TEMP_TEST_1.dmp
-rw-r----- 1 ora11g dba   466944 Jun 10 01:43 TEST_1.dmp
-rw-r----- 1 ora11g dba    69632 Jun 10 01:43 TEST_DATA_1.dmp
-rw-r----- 1 ora11g dba 39018496 Jun 10 01:43 TT_1.dmp
-rw-r----- 1 ora11g dba 43634688 Jun 10 01:43 TT_2.dmp
-rw-r----- 1 ora11g dba 30531584 Jun 10 01:43 T_TEMP_1.dmp

在比较同样的数据量的情况下,sqlloader可能需要大约120G的容量,而对于外部表来说,大概只需要40G左右的空间。

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

海量数据迁移之外部表并行抽取的相关文章

海量数据迁移之外部表切分

在前几篇中讨论过海量数据的并行加载,基本思路就是针对每一个物理表都会有一个对应的外部表,在做数据迁移的时候,如果表有上百G的时候,一个物理表对应一个外部表性能上会没有任何提升.如果需要做数据插入的时候,对undo是极大的挑战,从某种程度上而言,性能应该要比datapump要差.这个时候可以考虑一个物理表对应多个外部表,比如一个表有100G.可以考虑生成100个external dump 文件,然后加载生成100个外部表,每个dump文件对应一个外部表,这样做数据的插入的时候就相对容易控制了.每一

海量数据迁移之外部表加载

在并行生成了大量的dump文件后,可以在目标环境上对数据进行加载,这个加载的过程时间极短,都基本可以在毫秒级完成. 由于在外部表的加载过程中需要知道表结构的定义,所以可以通过如下的脚本得到表定义的基本语句,输出和desc类似. 因为目标环境中的表结构可能会和源dump文件中的表结构有一定的出入.所以可以在目标环境中生成表结构的定义语句. 批量加载生成的dump文件. 大体的效果如下 根据目标环境的表结构定义,生成黄色部分的表结构定义语句.然后在加载dump的时候,可以动态批量的加载dump文件,

阿里云RDS PostgreSQL OSS 外部表 - 并行写提速案例

标签 PostgreSQL , oss对象存储 , 阿里云RDS PG , 并行写 , dblink , 异步调用 , 异步任务监控 , OSS外部表 , 数据传输 背景 阿里云RDS PostgreSQL.HybridDB for PostgreSQL提供了一个非常强大的功能,OSS对象存储外部表. 阿里云的RDS PostgreSQL用户可以利用OSS存储冷数据(OSS外部表的形态呈现),实现冷热分离:也可以利用OSS作为数据的中转桥梁,打通其他云端业务,例如HDB FOR PostgreS

Greenplum insert的性能(单步\批量\copy) - 暨推荐使用gpfdist、阿里云oss外部表并行导入

标签 PostgreSQL , Greenplum , HybridDB for PostgreSQL , insert , copy , 外部表 , oss , gpfdist 背景 Greenplum是一款MPP数据库产品,优势是优良的OLAP性能,支持多节点并行计算,实现PB级数据量的实时分析. 除了分析能力,数据写入吞吐也是Greenplum的重要指标,Greenplum支持从master节点写入,也支持从segment节点并行写入. 从segment并行加载的话,性能是线性提升的,因为

海量数据迁移之传输表空间(一)

在自己接触的很多的数据迁移工作中,使用外部表在一定程度上达到了系统的预期,对于增量,批量的数据迁移效果还是不错的,但是也不能停步不前,在很多限定的场景中,有很多物理迁移中使用传统方法还是相当不错的,传输表空间就是一个样例. 最近的有一个数据迁移任务是需要把一些全新的数据表迁移到另外一个库中,因为这些表在目标库中不存在,所以使用逻辑迁移就显得有些力不从心了.尽管在速度可以接受的情况下,最大的痛处就是大量的归档文件了. 因为需要在原有的schema下增加一些全新的数据表,不是很肯定传输表空间的校验是

海量数据迁移之使用分区并行切分导入

在之前的章节中讨论过怎么把一个很大的分区表切分为若干的dump文件,在数据加载的时候能够同时做基于每个分区的数据导入,如果有些分区比较大,有几十个dump文件,那么这个分区做数据导入的时候是不能再进行并行切分了. 现在在准生产环境中先查找了如下的表,charge,memo,charge_rel数量级都过亿,而且memo表中还含有lob字段.其他两个分区尽管字段没有特殊之处,但是分区数很多.都在几百个左右. charge  133036878memo 186700029    CHARGE_REL

海量数据迁移之分区并行切分

在海量的数据迁移中,如果某个表特别大,可以考虑对表中的分区进行切分,比如某个表有100g,还有100个分区,那么可以考虑针对这100个分区,那么可以考虑把这100个分区看成100个表进行并行抽取,如果某个分区数据比较多,可能生成5个dump,那么着100个分区,就可能生成105个分区以上. 那么如果有100多个表,那么可能分区都算进来就可能有上千个.如何对这上千个dump进行最快的加载呢. 可以考虑基于分区的并行切分,里面可能还涉及一些算法的知识. 目前生成了如下的数据报告,我们需要基于这个报告

海量数据迁移之数据抽取流程

在之前的一些博文中花了大篇幅介绍了采用外部表抽取的一些细节,可能细节到了,基本原理的内容还希望再补充补充. 采用外部表抽取数据的流程图如下: 大体标注了一下抽取的基本结构,我们会尽量保证不去碰原本的数据源,会创建两个临时的用户,一个是只读用户,这个用户上只有同义词,只具有数据源中的select权限.这就对应上面红色标注的1,而另外一个用户是外部表用户,所有通过创建外部表都会在这个用户下进行,生成了dump文件之后,我们可以随时删除外部表,这个时候为了保证相关的drop操作不会牵扯到数据源,外部表

PostgreSQL · 实现分析 · PostgreSQL 10.0 并行查询和外部表的结合

title: PostgreSQL · 实现分析 · PostgreSQL 10.0 并行查询和外部表的结合 author: 义从 前言 大家都知道,PostgreSQL 近几大版本中加入了很多 OLAP 相关特性.9.6 的并行扫描应该算最大的相关特性.在今年发布的 10.0 中,并行扫描也在不断加强,新增了并行的索引扫描. 我们知道并行扫描是支持外部数据源的.在云上,有很多存储存储产品可以以外部数据源的形式做数据库的外部存储.例如,阿里云的 OSS 和 AWS 的 S3 都是绝佳的外部数据源