Oracle大数据量导入导出问题

时间:2022-02-07 22:06:46
目前对方是oracle11g,每天有170万条的数据会实时入库。对方数据库保存1年内的记录,目前数据量大概有4-5亿条。我们现在需要把对方数据库的数据同步到我们这边的oracle9i当中。用什么样的方法可以是同步的过程速度快,不影响对方的数据库?同步频率可以是小时,天,周,月。当然考虑到以后我们这边的查询方便,我们这边的表应该如何设计?如何优化数据库?
听说oracle有什么快照功能,分区功能。
小弟专注于java开发,对oracle了解甚少。欢迎大家讨论,提供解决思路

24 个解决方案

#1


很想帮你,技术不够,关注中。。。。

#2


“每天有170万条的数据会实时入库”,是一张表还是很多表?
如果有钱,可以考虑购买Quest公司的SharePlex或ORACLE公司的GoldenGate这种数据复制软件。

#3


每天170万的数据是录入到一同张表中。
购买其他的产品这种方式目前来说还不现实

#4


我也首先想问如二楼所说的问题,170万条是整个库还是一个表格,如果是一个表170万条,那真有点麻烦。
我就从个人来说一点点思路,希望对你有些帮助:

1、类似于这样的大表一般是需要创建分区的,表需要分区,索引也需要分区,这里只提到分区就是子表,一个子表ORACLE内部就是一个段的概念,我的博客内部正好刚写了一篇关于分区的介绍,你也可以参考其他的资料帮你提供参考,这个需要对分区专门研究,然后根据实际情况去做分区(因为从题目上也不是太明确你的要求),不然有些时候往往适得其反。

2、ORACLE快照就不是解决这个问题的了,他主要是对回滚段的一些处理记录,当你删除增加数据,即使提交了,也可以通过快照找到近期的数据,但是如果回滚段较小,被冲掉了,那就没办法了,就像做一个大型统计需要很长时间,中途若对统计的表进行增删改查操作即使COMMIT也不会在统计中运算,因为ORACLE会自己创建在执行SQL前给与一个时间戳TIMESTAMP和对应SCN号码,这个是绝对唯一的,如果出现脏块,就会到回滚段去找数据,若回滚段被冲掉,这个统计会报错。

3、在这样大数据量的转存过程中,建议使用分批转存(不要一次转存过来),并自己去编写日志,转存过程中,将目标表使用Hint中的/*+append*/进去并后带NOLOGGING,如:INSERT /*+append*/ INTO <table_name> NOLOGGING SELECT .. FROM ...;这样会以最小的日志编写方式进行高水位线插入,另外如果是同步数据可以使用到MERGE,自定义分表快速一次性插入使用INSERT ALL。

4、如果是一个表内部就有这么多数据,目标表需要进行分区,而且根据实际情况可以的话建议是二级分区,分区一定要找好下手点,不能乱分,不然往往分后的性能不如不分的情况,至于如何分区,这些都要依据实际情况而定,没有完全的定论,不过只要分区,最基本的就是你的分区字段是99%的情况都要用以查询条件,并可以迅速定位分区的字段,一个分区内部的数据不要太多,各个分区的数据较为均匀分布。

5、分区基础上创建分区索引,有全局索引和本地索引,据实际情况可以参考使用,保证通过分区索引快速定位数据范围和查找数据(针对提取少量数据,而不是全盘扫描)。

6、至于如何将高版本的数据同步到低版本,尤其跨越两个大版本,本来ORACLE 10后有一个数据泵,但是ORACLE 9I用不了,但是用SQL无益是最慢的,DMP就算是小版本的区别也可能会有点问题,SQL*LOADER是人工去完成导入导出工作,外部表是文件结构也需要先导出去而且对于大数据量的性能不容乐观,就我个人来说在可能的情况下用DB-LINK链接过去,可进行双数据库操作,不过DB-LINK转存过程注意分布式事务的一致性问题。

简单说就这些,细说就是经验和理论的东东很多,希望可以给你帮助。

#5


引用 4 楼 xieyuooo 的回复:
我也首先想问如二楼所说的问题,170万条是整个库还是一个表格,如果是一个表170万条,那真有点麻烦。
我就从个人来说一点点思路,希望对你有些帮助:

1、类似于这样的大表一般是需要创建分区的,表需要分区,索引也需要分区,这里只提到分区就是子表,一个子表ORACLE内部就是一个段的概念,我的博客内部正好刚写了一篇关于分区的介绍,你也可以参考其他的资料帮你提供参考,这个需要对分区专门研究,然后根……


支持,支持啊!

#6


数据传输可以尝试用jms来做

#7


如果一张表有这么多数据,
建议每天做一个分区,
每个分区按业务需求保存一定时间,
然后每天导出数据

1、导出数据文件
set feedback off;
set heading off;
set pagesize 0;
set termout off;
set trimspool on;
spool c:\test.csv;
select col1||','||col2 from test;
spool off;

2、建立导入控制文件test.ctl
load data
intfile 'c:\test.csv'
into table test
append
fields terminated by ','
(col1,
col2)

3、导入数据库
c:>sqlldr user/pass@tnsnames control=test.ctl direct=y streamsize=10485760

#8


>不影响对方的数据库

显然物化视图不太合适

如果每次都EXP\IMP, 又太麻烦了点。

用DBLINK链过去,自已想法办增量刷新,这样会好一些

#9


想办法做增量更新吧  看看对方表有没有最后更新时间或者序列号之类的

#10


以序列号为例 每天找出自己数据库最大的序列号
到对方数据库找出比此序列号更大的数据
再回来自己数据库比较更新

#11


你可以使用SQLLDR方法来导入数据。这种方式比较快。200W数据在20分钟就可以执行完毕。
但具体导入速度还需看你的服务器硬件配置。


下面提供SQLLDR基本语法
sqlldr user/pwd@serviceName control=load.ctl


load.ctl
-----------------------------------------------------------------
load data
infile 'C:\Documents and Settings\Administrator\桌面\数据文件.txt'  
append into table tableName //append 或者 replace   
fields terminated by ';' //分隔符   
(   
EMAIL CHAR,   
GENDER CHAR,   
AGE CHAR   
)
------------------------------------------------------------------ 

#12


我觉得你应该是指同步“insert"和update的数据吧,还是?delete的也要?

用streams.

#13


这么大的数据   小弟没做过  关注··

#14


引用 12 楼 liuyi8903 的回复:
我觉得你应该是指同步“insert"和update的数据吧,还是?delete的也要?

用streams.

就是定期把对方数据库的数据自动的导过来。应该我们这边的库应该只涉及到insert操作。

#15


问了一下公司的同事,有的说用物化视图,有的说用dblink方式。
不知道这2中方式有什么优缺点

#16


RMAN DUPLICATE DATABASE

RATE 分配低一点.

#17


exp/imp

#18


如果省钱的方式就自己写scripts吧。

有钱的话就用复制软件了,gg shareplex都可以。

#19


我觉得物化视图(materialized view)可能会比较实际
因为可以设计快速更新,可以减少网络间的传输,效率肯定是没得说了
可以参照我的博客materialized view

#20


如果表比较大,refresh的load会很高,而且有可能在高峰期时01555,另外,hwm高水位线的问题有时候造成慢。

#21


   之前我也遇到你这种情况!
    有两种方法供你参考:
   1.考虑你只有一张表,可以每天一个dmp文件。
   2.通过dblink,先来个全量拷贝,这个数据也不会很慢,4-5亿条数据。大概2-3个小时可以复制完。
     以后通过merge into 增量刷新!

   个人觉得2好点!

#22



dataguard

#23


物化视图和dblink联合使用
1 先在源服务器上建立快照索引 ;Create snapshot log on tablename;
2,目标服务器上建立dblink  dblink_anson ,并保证网络畅通,
3,目标服务器建立快照Create snapshot newname as select * from tablename@dblink_anson;
4 设置快照刷新频率: Alter snapshot newname refresh complete Start with   sysdate+30/24*60*60 next sysdate+1; 快照在30秒后完全刷新,以后每天这个时候刷新

#24


小组决定还是用物化视图的方式。
感谢大家的分享

#1


很想帮你,技术不够,关注中。。。。

#2


“每天有170万条的数据会实时入库”,是一张表还是很多表?
如果有钱,可以考虑购买Quest公司的SharePlex或ORACLE公司的GoldenGate这种数据复制软件。

#3


每天170万的数据是录入到一同张表中。
购买其他的产品这种方式目前来说还不现实

#4


我也首先想问如二楼所说的问题,170万条是整个库还是一个表格,如果是一个表170万条,那真有点麻烦。
我就从个人来说一点点思路,希望对你有些帮助:

1、类似于这样的大表一般是需要创建分区的,表需要分区,索引也需要分区,这里只提到分区就是子表,一个子表ORACLE内部就是一个段的概念,我的博客内部正好刚写了一篇关于分区的介绍,你也可以参考其他的资料帮你提供参考,这个需要对分区专门研究,然后根据实际情况去做分区(因为从题目上也不是太明确你的要求),不然有些时候往往适得其反。

2、ORACLE快照就不是解决这个问题的了,他主要是对回滚段的一些处理记录,当你删除增加数据,即使提交了,也可以通过快照找到近期的数据,但是如果回滚段较小,被冲掉了,那就没办法了,就像做一个大型统计需要很长时间,中途若对统计的表进行增删改查操作即使COMMIT也不会在统计中运算,因为ORACLE会自己创建在执行SQL前给与一个时间戳TIMESTAMP和对应SCN号码,这个是绝对唯一的,如果出现脏块,就会到回滚段去找数据,若回滚段被冲掉,这个统计会报错。

3、在这样大数据量的转存过程中,建议使用分批转存(不要一次转存过来),并自己去编写日志,转存过程中,将目标表使用Hint中的/*+append*/进去并后带NOLOGGING,如:INSERT /*+append*/ INTO <table_name> NOLOGGING SELECT .. FROM ...;这样会以最小的日志编写方式进行高水位线插入,另外如果是同步数据可以使用到MERGE,自定义分表快速一次性插入使用INSERT ALL。

4、如果是一个表内部就有这么多数据,目标表需要进行分区,而且根据实际情况可以的话建议是二级分区,分区一定要找好下手点,不能乱分,不然往往分后的性能不如不分的情况,至于如何分区,这些都要依据实际情况而定,没有完全的定论,不过只要分区,最基本的就是你的分区字段是99%的情况都要用以查询条件,并可以迅速定位分区的字段,一个分区内部的数据不要太多,各个分区的数据较为均匀分布。

5、分区基础上创建分区索引,有全局索引和本地索引,据实际情况可以参考使用,保证通过分区索引快速定位数据范围和查找数据(针对提取少量数据,而不是全盘扫描)。

6、至于如何将高版本的数据同步到低版本,尤其跨越两个大版本,本来ORACLE 10后有一个数据泵,但是ORACLE 9I用不了,但是用SQL无益是最慢的,DMP就算是小版本的区别也可能会有点问题,SQL*LOADER是人工去完成导入导出工作,外部表是文件结构也需要先导出去而且对于大数据量的性能不容乐观,就我个人来说在可能的情况下用DB-LINK链接过去,可进行双数据库操作,不过DB-LINK转存过程注意分布式事务的一致性问题。

简单说就这些,细说就是经验和理论的东东很多,希望可以给你帮助。

#5


引用 4 楼 xieyuooo 的回复:
我也首先想问如二楼所说的问题,170万条是整个库还是一个表格,如果是一个表170万条,那真有点麻烦。
我就从个人来说一点点思路,希望对你有些帮助:

1、类似于这样的大表一般是需要创建分区的,表需要分区,索引也需要分区,这里只提到分区就是子表,一个子表ORACLE内部就是一个段的概念,我的博客内部正好刚写了一篇关于分区的介绍,你也可以参考其他的资料帮你提供参考,这个需要对分区专门研究,然后根……


支持,支持啊!

#6


数据传输可以尝试用jms来做

#7


如果一张表有这么多数据,
建议每天做一个分区,
每个分区按业务需求保存一定时间,
然后每天导出数据

1、导出数据文件
set feedback off;
set heading off;
set pagesize 0;
set termout off;
set trimspool on;
spool c:\test.csv;
select col1||','||col2 from test;
spool off;

2、建立导入控制文件test.ctl
load data
intfile 'c:\test.csv'
into table test
append
fields terminated by ','
(col1,
col2)

3、导入数据库
c:>sqlldr user/pass@tnsnames control=test.ctl direct=y streamsize=10485760

#8


>不影响对方的数据库

显然物化视图不太合适

如果每次都EXP\IMP, 又太麻烦了点。

用DBLINK链过去,自已想法办增量刷新,这样会好一些

#9


想办法做增量更新吧  看看对方表有没有最后更新时间或者序列号之类的

#10


以序列号为例 每天找出自己数据库最大的序列号
到对方数据库找出比此序列号更大的数据
再回来自己数据库比较更新

#11


你可以使用SQLLDR方法来导入数据。这种方式比较快。200W数据在20分钟就可以执行完毕。
但具体导入速度还需看你的服务器硬件配置。


下面提供SQLLDR基本语法
sqlldr user/pwd@serviceName control=load.ctl


load.ctl
-----------------------------------------------------------------
load data
infile 'C:\Documents and Settings\Administrator\桌面\数据文件.txt'  
append into table tableName //append 或者 replace   
fields terminated by ';' //分隔符   
(   
EMAIL CHAR,   
GENDER CHAR,   
AGE CHAR   
)
------------------------------------------------------------------ 

#12


我觉得你应该是指同步“insert"和update的数据吧,还是?delete的也要?

用streams.

#13


这么大的数据   小弟没做过  关注··

#14


引用 12 楼 liuyi8903 的回复:
我觉得你应该是指同步“insert"和update的数据吧,还是?delete的也要?

用streams.

就是定期把对方数据库的数据自动的导过来。应该我们这边的库应该只涉及到insert操作。

#15


问了一下公司的同事,有的说用物化视图,有的说用dblink方式。
不知道这2中方式有什么优缺点

#16


RMAN DUPLICATE DATABASE

RATE 分配低一点.

#17


exp/imp

#18


如果省钱的方式就自己写scripts吧。

有钱的话就用复制软件了,gg shareplex都可以。

#19


我觉得物化视图(materialized view)可能会比较实际
因为可以设计快速更新,可以减少网络间的传输,效率肯定是没得说了
可以参照我的博客materialized view

#20


如果表比较大,refresh的load会很高,而且有可能在高峰期时01555,另外,hwm高水位线的问题有时候造成慢。

#21


   之前我也遇到你这种情况!
    有两种方法供你参考:
   1.考虑你只有一张表,可以每天一个dmp文件。
   2.通过dblink,先来个全量拷贝,这个数据也不会很慢,4-5亿条数据。大概2-3个小时可以复制完。
     以后通过merge into 增量刷新!

   个人觉得2好点!

#22



dataguard

#23


物化视图和dblink联合使用
1 先在源服务器上建立快照索引 ;Create snapshot log on tablename;
2,目标服务器上建立dblink  dblink_anson ,并保证网络畅通,
3,目标服务器建立快照Create snapshot newname as select * from tablename@dblink_anson;
4 设置快照刷新频率: Alter snapshot newname refresh complete Start with   sysdate+30/24*60*60 next sysdate+1; 快照在30秒后完全刷新,以后每天这个时候刷新

#24


小组决定还是用物化视图的方式。
感谢大家的分享