当数据量小时(20万行内),plsqldev、sqlplus的spool都能比较方便进行csv导出,但是当数据量到百万千万级,这两个方法非常慢而且可能中途客户端就崩溃,需要使用其他方法。

一、 sqluldr2工具

1. 优缺点

  • 优点:高效;支持功能较多;用户只需有对应表查询权限;可以在从库执行
  • 缺点:目前已没有再维护,只能找到基于oracle 10.2的版本(高版本目前还可以用);密码必须要跟在用户名后面输,安全性不足

2. 下载安装

  • 百度云链接:https://pan.baidu.com/s/1V8eqyyYsbJqQSD-Sn-RQGg 提取码:6mdn

下载完后并解压会生成4个文件

  • sqluldr2.exe  用于32位windows平台
  • sqluldr264.exe  用于64位windows平台
  • sqluldr2_linux32_10204.bin  用于linux32位操作系统
  • sqluldr2_linux64_10204.bin  用于linux64位操作系统

Windows的可以直接用,Linux的需要加执行权限。

chmod +x sqluldr2_linux64_10204.bin

[转帖]oracle导出千万级数据为csv格式_sql

3. 导出csv格式数据

/data/bak目录需要预先建好,oracle用户可写。如果查询语句较复杂,可以建成一个临时视图,通过视图导出,避免写一堆语句。

./sqluldr2_linux64_10204.bin myuser/xxxxxxx query="select * from tmp1201_all_v" head=yes file=/data/bak/tmp1201_all_v.csv

测试700万左右数据导出约12分钟(15:47开始执行),主要是视图查询较慢,导出表应该更快。

[转帖]oracle导出千万级数据为csv格式_SQL_02

二、 利用存储过程

1. 优缺点

  • 优点:效率较高;原生sql、目前无版本问题;可自行增加需要功能
  • 缺点:需要sys权限;只能在主库执行;功能相对较少

2. sys用户建存储过程

代码转载自

CREATE OR REPLACE PROCEDURE SQL_TO_CSV

 


(

 


 P_QUERY IN VARCHAR2, -- PLSQL文


 


 P_DIR IN VARCHAR2, -- 导出的文件放置目录


 


 P_FILENAME IN VARCHAR2 -- CSV名


 


 )

 


 IS


 


  L_OUTPUT UTL_FILE.FILE_TYPE;

 


  L_THECURSOR INTEGER DEFAULT DBMS_SQL.OPEN_CURSOR;

 


  L_COLUMNVALUE VARCHAR2(4000);

 


  L_STATUS INTEGER;

 


  L_COLCNT NUMBER := 0;

 


  L_SEPARATOR VARCHAR2(1);

 


  L_DESCTBL DBMS_SQL.DESC_TAB;

 


  P_MAX_LINESIZE NUMBER := 32000;

 


BEGIN

 


  --OPEN FILE


 


  L_OUTPUT := UTL_FILE.FOPEN(P_DIR, P_FILENAME, 'W', P_MAX_LINESIZE);

 


  --DEFINE DATE FORMAT


 


  EXECUTE IMMEDIATE 'ALTER SESSION SET NLS_DATE_FORMAT=''YYYY-MM-DD HH24:MI:SS''';

 


  --OPEN CURSOR


 


  DBMS_SQL.PARSE(L_THECURSOR, P_QUERY, DBMS_SQL.NATIVE);

 


  DBMS_SQL.DESCRIBE_COLUMNS(L_THECURSOR, L_COLCNT, L_DESCTBL);

 


  --DUMP TABLE COLUMN NAME


 


  FOR I IN 1 .. L_COLCNT LOOP

 


    UTL_FILE.PUT(L_OUTPUT,L_SEPARATOR || '"' || L_DESCTBL(I).COL_NAME || '"'); --输出表字段


 


    DBMS_SQL.DEFINE_COLUMN(L_THECURSOR, I, L_COLUMNVALUE, 4000);

 


    L_SEPARATOR := ',';

 


  END LOOP;

 


  UTL_FILE.NEW_LINE(L_OUTPUT); --输出表字段


 


  --EXECUTE THE QUERY STATEMENT


 


  L_STATUS := DBMS_SQL.EXECUTE(L_THECURSOR);

 


 

 


  --DUMP TABLE COLUMN VALUE


 


  WHILE (DBMS_SQL.FETCH_ROWS(L_THECURSOR) > 0) LOOP

 


    L_SEPARATOR := '';

 


    FOR I IN 1 .. L_COLCNT LOOP

 


      DBMS_SQL.COLUMN_VALUE(L_THECURSOR, I, L_COLUMNVALUE);

 


      UTL_FILE.PUT(L_OUTPUT,

 


                  L_SEPARATOR || '"' ||


 


                  TRIM(BOTH ' ' FROM REPLACE(L_COLUMNVALUE, '"', '""')) || '"');

 


      L_SEPARATOR := ',';

 


    END LOOP;

 


    UTL_FILE.NEW_LINE(L_OUTPUT);

 


  END LOOP;

 


  --CLOSE CURSOR


 


  DBMS_SQL.CLOSE_CURSOR(L_THECURSOR);

 


  --CLOSE FILE


 


  UTL_FILE.FCLOSE(L_OUTPUT);

 


EXCEPTION

 


  WHEN OTHERS THEN


 


    RAISE;

 



END;

 


/

3. 创建导出目录

/data/bak目录需要预先建好,oracle用户可写。如果查询语句较复杂,可以建成一个临时视图(sys用户下),通过视图导出,避免写一堆语句。

create or replace directory OUT_PATH_TEMP as '/data/bak';

4. 执行存储过程

begin

 


sql_to_csv('select * from tmp1201_all_v','OUT_PATH_TEMP','tmp1201_all_v.csv');  

 



end;

 


/

测试700万左右数据导出约23分钟,主要是视图查询较慢,导出表应该更快。

[转帖]oracle导出千万级数据为csv格式_sql_03

参考

oracle存储过程(将表导出成csv)_菜鸟冲锋号的博客

sqluldr2 学习心得 - 蒙奇D杰

【Oracle】oracle sqluldr2工具使用方法 - 简书