ORACLE数据库Exp、imp以及expdp、impdp以及对exp空表的导出问题

http://blog.csdn.net/dws2004/article/details/6315706

http://blog.csdn.net/yudehui/article/details/8078294


1。exp导出空表

1、导入导出(imp/exp) 某个用户表下面的所有数据

导出某个用户的所有对象

[oracle@cddserver1 ~]$ echo $NLS_LANG
AMERICAN_AMERICA.ZHS16GBK
[oracle@cddserver1 ~]$ exp testa/testa@orcl owner= testa file=/home/oracle/testa.dmp

导入某个用户的数据

[oracle@cddserver1 ~]$imp testa/testa fromuser =testa touser =testa file=/home/oracle/testa.dmp

注意:

要保证导入的用户的表空间的名称和导出的表空间名称是一样的

导入前最好保证要导入用户里面没有重复的对象和数据,要不导入会不成功。

 11G中有个新特性,当表无数据时,不分配segment,以节省空间,这样就会没有导出数据 

2、导出和导入某个用户下的某张表

[oracle@developserver ~]$  exp test/test file=/home/oracle/Desktop/t_area.dmp log=t_area.log tables=t_area

[oracle@developserver ~]$ imp  file=/home/oracle/Desktop/t_area.dmp tables=t_area commit=y ignore=y

注意导入之前最好保证表中的数据为空 

3、解决使用oracle11g无法导出(exp/imp)空表的问题

解决方法,原理就是往所有的空表中插入数据:

搞了我好久,最后查到这个方法。

方法1:

在图形工具中,如sqldeveloper,pl/sqldeveloper用以下这句查找空表

select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0

把查询结果导出,就是把语句复制出来单独运行

方法2:

sqlplus 中执行下面的程序

--查询当前用户下的所有空表,并生成空表的插入语句脚本
create or replace

procedure  generate_tab_segement is
v_table                      NVARCHAR2(200);
v_sql                        VARCHAR2(200);
v_q                          NUMBER;
v_char_value                 NVARCHAR2(10);
v_varchar2_value             NVARCHAR2(10);
v_number_value               NVARCHAR2(10);
v_date_value                 NVARCHAR2(10);
v_add_value                  NVARCHAR2(10);
v_separate_value             NVARCHAR2(10);
v_insert_sql                 NVARCHAR2(4000);
col_num                      NVARCHAR2(200);
tb_name                      NVARCHAR2(200);
TYPE TCUR IS REF CURSOR; 
c2 TCUR;

begin

     FOR r1 IN (SELECT table_name tn FROM tabs) LOOP
        BEGIN
            v_table   :=r1.tn;
            v_sql     := 'SELECT count(*) as q FROM ' || v_table || ' where rownum = 1';
            v_char_value := '''1''';
            v_varchar2_value := '''1''';
            v_number_value := '1';
            v_date_value := 'sysdate';
            v_separate_value := ',';
            v_insert_sql := 'insert into ';
            v_add_value :='null';
            OPEN c2 FOR v_sql ; 
            LOOP
                FETCH c2 INTO v_q;
                EXIT WHEN c2%NOTFOUND;

                IF v_q = 0 THEN
                    --DBMS_OUTPUT.PUT_LINE(v_table);
                    --构造插入行
                    FOR user_null_table IN (select to_char(count(*)) as col_num,
                    t.TABLE_NAME as tb_name
                    from user_tab_columns t
                    where t.TABLE_NAME= v_table
                    group by t.TABLE_NAME) LOOP
                        BEGIN
                            col_num      := user_null_table.col_num;
                            tb_name      := user_null_table.tb_name;
                            v_insert_sql := 'insert into ';

                            v_insert_sql := v_insert_sql || tb_name || ' values(' ;
                            FOR user_tab_cols IN (select * from user_tab_columns t where t.TABLE_NAME = tb_name ORDER BY t.COLUMN_ID) LOOP

                                BEGIN                                                                   
                                    v_add_value :='null';                                    
                                    IF user_tab_cols.COLUMN_ID = col_num THEN 
                                       v_separate_value := '';
                                    else
                                        v_separate_value := ',';
                                    END IF;                                   
                                    if user_tab_cols.DATA_TYPE = 'CHAR' THEN
                                        v_add_value := v_char_value;
                                    END if;
                                    
                                    IF user_tab_cols.DATA_TYPE = 'VARCHAR2' THEN
                                        v_add_value := v_varchar2_value;
                                    END if;                                    
                                    IF user_tab_cols.DATA_TYPE = 'NVARCHAR2' THEN
                                        v_add_value := v_varchar2_value;
                                    END if;                                    
                                    IF user_tab_cols.DATA_TYPE = 'NUMBER' THEN
                                        v_add_value := v_number_value;
                                    END if;                                    
                                    IF user_tab_cols.DATA_TYPE = 'LONG' THEN
                                        v_add_value := v_number_value;
                                    END if;                                    
                                    IF user_tab_cols.DATA_TYPE = 'DATE' THEN
                                        v_add_value := v_date_value;
                                    END IF;                                    
                                    IF substr(user_tab_cols.DATA_TYPE,0,9) = 'TIMESTAMP' THEN
                                        v_add_value := v_date_value;
                                    END IF;                                   
                                    v_insert_sql := v_insert_sql || v_add_value ||
                                        v_separate_value;                                
                                end;
                            END LOOP;                            
                            v_insert_sql := v_insert_sql || ');';
                            DBMS_OUTPUT.PUT_LINE(v_insert_sql);                           
                        end;
                    END LOOP;                
                end if;
            END LOOP;
            CLOSE c2;
        end;
    END LOOP;
end generate_tab_segement;

/

然后用图形界面工具去调用该存储过程,让存储过程语句执行一次,并起作用,不知道什么原因有些表的数据没有插入进去,为了保证不会出错,大家可以将执行完显示的SQL语句在执行一次就绝对不会错误。


然后将执行完的结果复制一次,在用图形界面执行一次,就可以了

 方法3:默认给任何空表都分配空间

设置deferred_segment_creation 参数

SQL> alter system set deferred_segment_creation=false;

SQL> show parameter deferred_segment_creation

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
deferred_segment_creation            boolean     FALSE 

该参数值默认是TRUE,当改为FALSE时,无论是空表还是非空表,都分配segment。

需注意的是:该值设置后对以前导入的空表不产生作用,仍不能导出,只能对后面新增的表产生作用。如需导出之前的空表,只能用第一种方法。

参考

http://blog.csdn.net/wyzxg/article/details/2123403

http://blog.csdn.net/dws2004/article/details/6315706

http://tech.ddvip.com/2008-08/121991685458513.html 

http://hi.baidu.com/aweiwenyuan/blog/item/e115ec526b5e830b0df3e302.html

2。导入、导出性能

EXP常规模式、EXP直接路径模式和EXPDP三种方式导出的性能对比 
1.首先是EXP的常规路径导出: 
exp zhejiang/zhejiang file=/data1/zj_regular.dmp buffer=20480000 
常规EXP导出方式执行了1小时24分钟。 

2.直接路径导出方式: 
exp zhejiang/zhejiang file=/data1/zj_direct.dmp buffer=20480000 
recordlength=65535 direct=y 
直接路径导入用时18分钟,比常规路径导出速度有一个明显的提高。 



3.数据泵的导出速度。 
expdp zhejiang/zhejiang dumpfile=zj_datapump.dp directory=d_test schemas=zhejiang 
数据泵的导出时间仅用了14分钟,比直接路径导入方式还快了20%多。而且观察三个导出文件的大小可以发现,导出速度越快对应的文件也越小,其中数据泵的导出方式得到的文件要比EXP方式小将近1.5G。 


IMP和IMPDP导入性能对比 
1.IMP的导入速度: 
imp zhejiang/zhejiang file=/data1/zj_regular.dmp full=y buffer=20480000 log=/data1/zj_regular.log 
IMP导入花费了3小时17分钟, 

2.IMPdp的导入速度: 
impdp zhejiang/zhejiang DUMPFILE=zj_datapump.dp DIRECTORY=d_test FULL=y LOGFILE=zj_datapump.log 
数据泵的导入操作居然花了3个小时8分钟的时间,和IMP的导入速度十分接近,看来并非所有情况下都像Oracle描述的那样,数据泵的导入比普通导入效率有大幅度的提高。 

上面一篇文章的测试中发现IMPDP的导入速度和IMP导入速度相差无几。而Oracle在介绍数据泵的时候,提到IMPDP的导入速度最高是IMP的10倍。不过好在IMPDP还是可以优化调整的,那就是通过设置PARALLEL来提高IMPDP的并行度。 
首先还是看一下CPU的数量: 

SQL> show parameter cpu 


由于数据库服务器的CPU个数为2,下面尝试设置PARALLEL为2来进行导入 
impdp zhejiang/zhejiang DUMPFILE=zj_datapump.dp DIRECTORY=d_test FULL=y LOGFILE=zj_datapump.log parallel=2 

采用并行度为2的导入方式,发现速度果然提高了很多。并行度为1的导入速度是3小时8分钟,而现在用了不到2个半小时。 
由于并行度设置不应该超过CPU数的2倍,因此尝试平行度3和4的导入,导入时间和并行度2十分接近。看来已经无法再使用通过提高并行度的方法来提高性能了。 


1.先看直接导出的性能: 

$ expdp zhejiang/zhejiang directory=d_test dumpfile=zhejiang.dp 
整个导出操作大概用了14分半, 

2.尝试使用并行度2进行导出,这时仍然设置一个导出的数据文件: 
$ expdp zhejiang/zhejiang directory=d_test dumpfile=zhejiang_p2_1file.dp parallel=2 

整个导入过程不到14分钟,不过这个性能的提升实在不是很明显。不过这是有原因的,由于设置了并行度,两个进程在同时执行导出操作,但是二者要将导出的数据写入同一个数据文件中,因此必然会导致资源的争用 

3.仍然使用并行度2,但是同时设置两个数据文件再次检查导出性能: 
$ expdp zhejiang/zhejiang directory=d_test dumpfile=zhejiang_p2_2file1.dp,zhejiang_p2_2file2.dp parallel=2 

这次导出仅仅用了10分半,导出的效率大大的提高。 

4.测试一下并行度4,分别导出到4个数据文件中: 
用了9分钟整导出完成,设置成并行度4仍然可以获得一定的性能提升,但是并不明显了,这主要是由于整个性能的瓶颈已经不是单个进程的处理能力,多半性能的瓶颈已经变成了磁盘IO瓶颈,此时单单靠增加并行度已经无法明显提升性能了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值