oracle 大字段表进行导出导入后空间占用大不同,原来是字段压缩惹的祸!

2024年 7月 25日 48.7k 0

生产上有一张大字段的表,大小300G左右,将其通过expdp命令导出,并通过impdp导入一个测试库后,发现其占用空间竟然比生产库大了很多,导入后的空间的占了700G左右。这是怎么回事,按理说,导入后空间不应该大这么多。由于涉及敏感信息,这里就自己创建一个测试表,复现一下整个过程。

1、导出大字段表

涉及大字段表,为了加快导出速度,我们可以根据rowid分片进行导出,具体导出脚本可以参考[linux和window下基于rowid分片,加快进行导出和导入clob大字段的脚本] 这篇文章。

oracle 大字段表进行导出导入后空间占用大不同,原来是字段压缩惹的祸!-1

可以看到这张表预估值大小2M左右,可实际每个分片导出占用了30M多(一共有3个分片,总的话就快100M了)
oracle 大字段表进行导出导入后空间占用大不同,原来是字段压缩惹的祸!-2

也许你可能认为是不是预估的不准确,那自己去数据库上查一下看看这张表到底占用多大呢

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大字段的脚本] 这篇文章。
oracle 大字段表进行导出导入后空间占用大不同,原来是字段压缩惹的祸!-3

看一下导入完成后,去数据库里查一下占用大小,竟然有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);

表已创建。

重新导入数据,查看表占用大小
oracle 大字段表进行导出导入后空间占用大不同,原来是字段压缩惹的祸!-4

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

目标端表结构改完后,其占用大小与源端一致。

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论