给oracle逻辑导出clob大字段、大数据量表提提速


前言

Oracle在做数据迁移、还原测试库以及其他需要导出、导入数据的需求下,我们常用到数据泵来进行数据的转移操作,但往往很多事后我们要操作的库数据量都非常大,且数据库中clob字段非常多,就给我们导出带来了一些问题,导出慢或者卡在那里很久不动等问题;

有小伙伴可能会说你开并行不就行了吗?事实上当你数据库中大对象数据量占用较大时候,你会发现开并行没有任何用,那么怎么解决这个问题呢?那么思路是先排除大对象的表;然后大表再通过rowid切片多个进程导出导入。


提示:以下是本篇文章正文内容,下面案例可供参考

一、大表数据

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
截图中可以看到,此表占用446G数据量,压缩完后大小为51G,开了2个进程并行,但没有效果,最终执行了10小时,时间是非常久的。

附:查询大表

--查看大对象,先排除导出,然后再单独导出
SELECT owner,tablespace_name,case SEGMENT_type
         when 'LOBSEGMENT' then
          (select table_name || '.' || column_name
             from dba_lobs t
            where t.segment_name = s.segment_name)
         else
          SEGMENT_NAME
       end as SEGMENT_NAME,
       BYTES / 1024 / 1024 MB,
       BYTES / 1024 / 1024 / 1024 GB
  FROM DBA_SEGMENTS s
 Order By 4 Desc,3 asc;

二、解题思路

1.导出排除大表的数据

命令参考:

expdp system/oracle@ip:1521/sidname directory=datapump_dir parallel=8 cluster=N dumpfile=exp_full0824_%U.dmp logfile=exp_full_20230824.log schemas=usrname COMPRESSION=ALL exclude=statistics exclude=TABLE:\"in\(\'table_name\'\)\"

在这里插入图片描述
这里可以看到排除大表后整体导出时间下降到了17分钟!!!

2.rowid切片导出大表数据

rowid切片导出数据是从0开始,我们需要知道rowid的分配来控制最终想执行的并行数。

Linux代码如下(示例):

#!/bin/bash
chunk=9
for ((i=0;i<=8;i++));
do
expdp system/oracle TABLES=tablename QUERY=tablename:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\, ${chunk}\) = ${i}\" directory=DMP dumpfile=TX_${i}.DMP logfile=TX_${i}.log &
echo $i
sleep 10
done 

Windows代码如下(示例):

@echo off
#这里可以带上IP地址、端口、sid
set connStr=system/oracle@ip:1521/sid_name
#这里指的并行数
set chunk=10
#sid_name
set oracle_sid=orcl
#oracle_home路径注意bin后边的‘\’
set oracle_home_path=d:\oracle\product\10.2.0\db_1\bin\

rem 格式:FOR /L %variable IN (start,step,end) DO command [command-parameters]
#10个并行,0~9(开始标号、每次增加量、结束标号)
for /l %%a in (0,1,9) do (
start /b %oracle_home_path%expdp %connStr% TABLES=table_name QUERY=table_name:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,%chunk%\) = %%a\" directory=expdpdump dumpfile=TX_%%a.DMP logfile=TX_%%a.log
timeout 10 >nul 2>nul
)

手工执行代码如下(示例):

#如下,打开三个窗口分别粘贴执行,如果要开更多的进程,需要更改3后后面的0~2
SQL> create or replace directory dmp as 'D:\dump\';
SQL> grant read,write on directory dmp to public;

expdp system/oracle tables=table_name  QUERY=table_name:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,3\) = 0\" directory=DMP dumpfile=xxxx_0.dmp logfile=xxxx_0.log
expdp system/oracle tables=table_name  QUERY=table_name:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,3\) = 1\" directory=DMP dumpfile=xxxx_1.dmp logfile=xxxx_1.log
expdp system/oracle tables=table_name  QUERY=table_name:\"where mod\(dbms_rowid.rowid_block_number\(rowid\)\,3\) = 2\" directory=DMP dumpfile=xxxx_2.dmp logfile=xxxx_2.log
)

在这里插入图片描述

在这里插入图片描述
以上我拿一张14G数据表进行测试,3个并行度执行实际4分半,实际测试中切片导出数据也可以加压缩参数。
在这里插入图片描述
对比此张图可以看到我的切片测试已将导出实际提升了2倍左右,如果并行度更高的话,那么我们的整体时间会成倍降低。

3.rowid切片导入大表数据

导入前准备

在导入大表数据之前需要做的是:

#确保大表所在的表空间存在
select table_name,tablespace from user_tables where table_name='TABLE_NAME';
#创建用户以及表结构,建议使用plsql查询
SELECT DBMS_METADATA.GET_DDL('TABLE','TABLE_NAME') from DUAL;

linux代码如下(示例):

#!/bin/bash
for ((i=0;i<=8;i++));
do
#echo dumpfile=TX_${i}.DMP
impdp \"/ as sysdba\" directory=impdpdump dumpfile=TX_${i}.DMP logfile=impdp_TX_${i}.log DATA_OPTIONS=DISABLE_APPEND_HINT TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y CONTENT=DATA_ONLY &
sleep 10
done

windows代码如下(示例):

@echo off

set connStr=system/oracle
set oracle_sid=orcl
set oracle_home_path=d:\oracle\product\10.2.0\db_1\bin\

rem 格式:FOR /L %variable IN (start,step,end) DO command [command-parameters]

for /l %%a in (0,1,9) do (
rem 11g upper >start /b %oracle_home_path%impdp %connStr% directory=impdpdump dumpfile=TX_%%a.DMP logfile=imp_TX_%%a.log DATA_OPTIONS=DISABLE_APPEND_HINT TRANSFORM=DISABLE_ARCHIVE_LOGGING:Y CONTENT=DATA_ONLY

start /b %oracle_home_path%impdp %connStr% directory=impdpdump dumpfile=TX_%%a.DMP logfile=imp_TX_%%a.log CONTENT=DATA_ONLY
timeout 10 >nul 2>nul
)

在这里插入图片描述
测试表导入成功,和切片导出的时间基本相同。

三、导出时业务卡顿如何停止

select s.inst_id,to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') "DATE", s.program, s.sid, 'orakill orcl2 '||spid,'kill -9 '||spid,  
       s.status, s.username, d.job_name, p.spid, s.serial#, p.pid ,'ALTER SYSTEM KILL SESSION '||''''||s.SID||','||s.SERIAL#||',@'||s.inst_id||''''||' IMMEDIATE;' killse
  from gv$session s, gv$process p, dba_datapump_sessions d  
 where p.addr=s.paddr and s.saddr=d.saddr and s.inst_id=p.inst_id and s.inst_id=d.inst_id; 

select 'orakill orcl '||spid ,'ALTER SYSTEM KILL SESSION '||''''||t1.SID||','||t1.SERIAL#||''''||' IMMEDIATE;' killse
--,'kill -9 '||spid
                from sys.gV_$PROCESS t,gv$session t1,dba_datapump_sessions d 
                where t.addr=t1.paddr and t1.saddr=d.saddr
                and t1.Type='USER' and t1.username is not null;

select 'drop table ' || owner_name || '.' || job_name || ' purge;'  from dba_datapump_jobs where state = 'NOT RUNNING' ;

参考文献:https://mp.weixin.qq.com/s/pKNe2EzpB_PM0itpa4jrdA

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 要导出和导入Oracle数据库中的CLOB和BLOB数据类型,可以使用以下方法: 1. 使用Oracle自带的exp和imp工具导出和导入整个数据库或特定的数据。在导出时,使用参数“file=clob_data.dmp”或“file=blob_data.dmp”指定导出文件名。在导入时,使用参数“file=clob_data.dmp”或“file=blob_data.dmp”指定导入文件名。 2. 使用Oracle SQL Developer工具导出和导入特定的数据。在导出时,选择要导出,右键点击选择“导出”选项,选择“导出数据”并选择“导出为LOB文件”。在导入时,选择要导入的,右键点击选择“导入”选项,选择“导入数据”并选择“从LOB文件导入”。 3. 使用PL/SQL代码导出和导入CLOB和BLOB数据。在导出时,使用SELECT语句查询CLOB或BLOB列的值,并将其写入文件中。在导入时,使用INSERT语句将文件中的值插入到CLOB或BLOB列中。 以上是几种常见的导出和导入Oracle数据库CLOB和BLOB数据的方法。具体使用哪种方法取决于具体情况和需求。 ### 回答2: Oracle是一个广泛使用的关系型数据库,其中包含了CLOB(字符大对象)和BLOB(二进制大对象)类型的数据。这些数据类型通常用于存储大型文本和图像等二进制数据。在Oracle中,导出和导入CLOB和BLOB数据是非常常见的任务。本文将介绍如何导出和导入这些类型的数据。 首先,我们需要了解Oracle供的导出工具是exp和expdp。exp是旧版工具,而expdp是新版工具。在导出CLOB和BLOB数据时,我们建议使用expdp,因为它是专门为大量导出数据而设计的。下面我们来看看导出CLOB数据的方法: 1. 使用expdp导出 使用expdp命令导出CLOB数据需要指定以下参数: - expdp system/password tables=table_name directory=directory_name dumpfile=file_name.dmp lob_file=file_name.log EXCLUDE=STATISTICS 其中table_name是要导出名,directory_name是导出文件的路径,file_name是导出文件的名称,lob_file是LOB类型的文件的名称。 2. 使用SQL*Plus导出 我们也可以使用SQL*Plus命令导出CLOB数据。以下是步骤: 1)使用SQL*Plus连接到Oracle数据库。 2)使用以下命令在本机上创建目录 OBJECT_DIR: CREATE OR REPLACE DIRECTORY OBJECT_DIR AS 'C:\TEMP'; 3)使用以下命令导出CLOB数据: SET LONG 10000 SET PAGESIZE 0 SET LINESIZE 1000 SET FEEDBACK OFF SPOOL CLOB_Export.sql SELECT 'SELECT ' || column_name || ' FROM ' || table_name || ' WHERE ' || where_clause || ';' FROM all_tab_cols WHERE data_type = 'CLOB' AND table_name = 'TABLE_NAME'; SPOOL OFF 4)使用以下命令将生成的SQL脚本文件CLOB_Export.sql导出到本地目录: exp userid=username/password file=dumpfile.dmp owner=owner_name log=clob_export.log 接下来我们会介绍如何导入CLOB和BLOB数据。 1. 使用impdp导入 使用impdp命令导入CLOB数据需要指定以下参数: - impdp system/password directory=directory_name dumpfile=file_name.dmp logfile=file_name.log tables=table_name 其中directory_name是导入文件的路径,file_name是导入文件的名称,table_name是要导入数据的的名称。 2. 使用SQL*Plus导入 我们也可以使用SQL*Plus命令导入CLOB数据。以下是步骤: 1)使用SQL*Plus连接到Oracle数据库。 2)使用以下命令在本机上创建LOB的目录 LOB_DIR: CREATE OR REPLACE DIRECTORY LOB_DIR AS 'C:\TEMP'; 3)使用以下命令在Oracle中创建LOB: CREATE TABLE lob_table ( lob_column CLOB ); 4)使用以下命令将LOB类型的文件loaded_file.xml导入到LOB中: INSERT INTO lob_table (lob_column) VALUES (EMPTY_CLOB()); SELECT lob_column FROM lob_table FOR UPDATE; DECLARE infile BFILE :=BFILENAME('OBJECT_DIR', 'loaded_file.xml'); lob_loc CLOB; BEGIN DBMS_LOB.OPEN(lob_column, DBMS_LOB.LOB_READWRITE); DBMS_LOB.LOADFROMFILE(lob_column, infile, DBMS_LOB.GETLENGTH(infile)); DBMS_LOB.CLOSE(lob_column); COMMIT; END; / 以上是导出导入CLOB/BLOB数据的两种方法,根据实际情况可以选择使用expdp、impdp或SQL*Plus导出和导入。然而在导入CLOB/BLOB时,需要特别注意数据库版本以及LOB大小限制等问题。 ### 回答3: 在Oracle中,CLOB和BLOB是用来存储大文本和二进制数据的数据类型。有时候我们需要对这些数据进行导入和导出。在这篇文章中,我会介绍如何将CLOB和BLOB数据导入和导出导出CLOB/BLOB数据 在Oracle中,可以使用DBMS_LOB包来导出CLOB和BLOB数据。首先,我们需要使用SELECT语句来查询需要导出的数据。查询的结果会以一个CLOB或BLOB对象的形式存在,然后我们可以把这个对象导出到一个文件中。以下是导出CLOB和BLOB对象到文件中的步骤: 1.查询需要导出的数据 例如,我们可以使用以下SELECT语句来查询一个CLOB中的数据: SELECT clob_column FROM clob_table; 2.将查询结果存储到变量中 为了方便将查询结果导出到文件中,我们需要将查询结果存储到一个变量中。我们可以使用PL/SQL或SQL*Plus来完成这个任务。以下是一个PL/SQL的例子: DECLARE my_data CLOB; BEGIN SELECT clob_column INTO my_data FROM clob_table; END; 3.将变量的值导出到文件中 使用DBMS_LOB包中的函数,可以将变量的值导出到文件中,以下是一个导出CLOB数据的例子: DECLARE my_data CLOB; my_file UTL_FILE.FILE_TYPE; BEGIN SELECT clob_column INTO my_data FROM clob_table; my_file := UTL_FILE.FOPEN('MY_DIR', 'my_file.txt', 'w'); DBMS_LOB.FILEEXPORT(my_file, my_data); UTL_FILE.FCLOSE(my_file); END; 注意: - 'MY_DIR'是Oracle指定的一个目录,需要在数据库前定义。 - 'my_file.txt'是导出文件的名称 - 'w'示以覆盖模式写入文件 这个例子将会把查询出来的CLOB数据导出为txt文件。 导入CLOB/BLOB数据 同样的,我们可以使用DBMS_LOB包来导入CLOB和BLOB数据。以下是导入CLOB和BLOB数据的步骤: 1.读取文件内容 使用UTL_FILE包中的函数,可以读取文件的内容到一个变量中,例如以下SQL*Plus的命令: DEFINE my_file='my_file.txt' DECLARE my_data CLOB; my_file UTL_FILE.FILE_TYPE; BEGIN my_file := UTL_FILE.FOPEN('MY_DIR', '&my_file', 'r'); UTL_FILE.GET_LINE(my_file, my_data); UTL_FILE.FCLOSE(my_file); END; 注意: - 'my_file.txt'是要导入到数据库的文件名称 - MY_DIR是Oracle指定的一个目录,需要在数据库前定义。 2.将变量的值导入到数据库中 使用INSERT语句将变量的值插入到CLOB中,例如以下的SQL*Plus命令: INSERT INTO clob_table (clob_column) VALUES (my_data); 注意: 在Oracle中,插入CLOB和BLOB数据时,要使用专门的函数,例如: INSERT INTO clob_table (clob_column) VALUES (TO_LOB('some text')); 以上就是导出和导入CLOB/BLOB数据的步骤。当然,在实际操作中可能会遇到各种各样的问题,我们需要仔细阅读相关的文档,查找正确的解决方案。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DBA狗剩儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值