生产上有一张大字段的表,大小300G左右,将其通过expdp命令导出,并通过impdp导入一个测试库后,发现其占用空间竟然比生产库大了很多,导入后的空间的占了700G左右。这是怎么回事,按理说,导入后空间不应该大这么多。由于涉及敏感信息,这里就自己创建一个测试表,复现一下整个过程。
1、导出大字段表
涉及大字段表,为了加快导出速度,我们可以根据rowid分片进行导出,具体导出脚本可以参考[linux和window下基于rowid分片,加快进行导出和导入clob大字段的脚本] 这篇文章。
可以看到这张表预估值大小2M左右,可实际每个分片导出占用了30M多(一共有3个分片,总的话就快100M了)
也许你可能认为是不是预估的不准确,那自己去数据库上查一下看看这张表到底占用多大呢
SQL> select round(sum(bytes)/1024/1024,2) from user_segments
where segment_name = 'T_CLOB' or
segment_name in ( select segment_name from user_lobs
where table_name = 'T_CLOB' );
ROUND(SUM(BYTES)/1024/1024,2)
-----------------------------
2.13
从数据库里查,这张表确实占用约2M左右,导出后反而大了很多。
2、导入数据
找了一个测试库,进行导入看看。导入脚本可以参考[linux和window下基于rowid分片,加快进行导出和导入clob大字段的脚本] 这篇文章。
看一下导入完成后,去数据库里查一下占用大小,竟然有170M
select round(sum(bytes)/1024/1024,2) from user_segments
2 where segment_name = 'T_CLOB' or
3 segment_name in ( select segment_name from user_lobs
4 where table_name = 'T_CLOB' );
ROUND(SUM(BYTES)/1024/1024,2)
-----------------------------
170.13
3、问题排查
从上面的结果看,导入目标库后占用空间确实比源库占用大很多(源端占用2M,目标端占用170M),为什么差距占用这么大呢?从dba_lobs 这个视图查了一下源和目标端这张表的信息,发现端倪:
源端
SQL> select owner,table_name,column_name,cache,compression,securefile from dba_lobs where owner='SZR' and table_name='T_CLOB';
OWNER TABLE_NAME COLUMN_NAM CACHE COMPRE SEC
-------------------- ------------------------------ ---------- ---------- ------ ---
SZR T_CLOB C NO HIGH YES
目标端
szr@orcl(1765)> select owner,table_name,column_name,cache,compression,securefile from dba_lobs where owner='SZR' and table_name='T_CLOB';
OWNER TABLE_NAME COLUMN_NAM CACHE COMPRESSION SECURE
-------------------- ---------- ---------- -------------------- ------------ ------
SZR T_CLOB C NO NO YES
可以看到,t_clob 的字段C在源端的compression的值是为HIGH,而目标端是NO。我们看一下源和目标端的表定义
源端:
SQL> set pages 0
set longchunksize 3000
set long 2000000000
select dbms_metadata.get_ddl('TABLE','T_CLOB','SZR') from dual;
CREATE TABLE "SZR"."T_CLOB"
( "A" NUMBER,
"B" VARCHAR2(50),
"C" CLOB
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "SZR"
LOB ("C") STORE AS SECUREFILE (
TABLESPACE "SZR" ENABLE STORAGE IN ROW CHUNK 8192
NOCACHE LOGGING COMPRESS HIGH KEEP_DUPLICATES
STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT))
目标端:
szr@orcl(1765)> set pages 0
szr@orcl(1765)> set longchunksize 3000
szr@orcl(1765)> set long 2000000000
szr@orcl(1765)> select dbms_metadata.get_ddl('TABLE','T_CLOB','SZR') from dual;
CREATE TABLE "SZR"."T_CLOB"
( "A" NUMBER,
"B" VARCHAR2(50),
"C" CLOB
) SEGMENT CREATION IMMEDIATE
PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT)
TABLESPACE "USERS"
LOB ("C") STORE AS SECUREFILE (
TABLESPACE "USERS" ENABLE STORAGE IN ROW CHUNK 8192
NOCACHE LOGGING NOCOMPRESS KEEP_DUPLICATES
STORAGE(INITIAL 106496 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0
BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT))
对比了源和目标端,目标端字段C为NOCOMPRESS,没开压缩,源端设置了字段C COMPRESS HIGH。
4、更改目标端表结构
将目标端的表结构定义更改成与源端一致
szr@orcl(1765)> drop table t_clob purge;
表已删除。
szr@orcl(1765)> CREATE TABLE t_clob
2 (a number, b varchar2(50), c CLOB)
3 LOB(c) STORE AS SECUREFILE (NOCACHE LOGGING COMPRESS HIGH KEEP_DUPLICATES);
表已创建。
重新导入数据,查看表占用大小
szr@orcl(1765)> select round(sum(bytes)/1024/1024,2) from user_segments
2 where segment_name = 'T_CLOB' or
3 segment_name in ( select segment_name from user_lobs
4 where table_name = 'T_CLOB' );
ROUND(SUM(BYTES)/1024/1024,2)
-----------------------------
2.13
目标端表结构改完后,其占用大小与源端一致。