暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 如何将表数据卸载到csv文件-数百万条记录的最快方法

askTom 2017-08-15
522

问题描述

我有一张10000万行的表。数据库中的表大小约为25 GB。
我需要将此数据卸载到csv文件中。
什么是最好的最快的方法来做到这一点。

我正在阅读有关使用cta来执行此操作的外部表,但我认为没有选择直接创建为CSV格式的表的选项,该格式创建ascii文件逗号分隔。它只给出了作为dmp oracle loader二进制文件的选项。

有没有办法做外部表-cta与服务器上的输出为CSV-acsii文件?我认为那将是理想的。

sql loader是将数百万个数据加载到oracle数据库中的本地行业之王,但为什么不反过来呢?

我尝试使用sql developer导出到csv,由于10000万行,它需要很长时间才能完成。100万行csv导出大约需要2个小时,因此您可以想象使用sql developer将是一个200小时的工作。


蟾蜍只是在这次尝试中崩溃了。

我尝试了sqlplus假脱机,这也花了很长时间,因为它必须扫描整个10000万数据集。

我没有尝试过去使用的旧utl文件。我不知道在这个新的多云世界中甚至支持此文件或utl文件的12c增强功能。但是任何顺序的事情都需要很长时间。

Spark和Cassandra可以并行化并在几分钟内完成此操作,但这是一个不同的架构。我的数据驻留在Oracle中

有没有一种方法可以并行化并在百万块中执行此操作,那么我可以合并unix中的100文件。



请建议?

专家解答

你说得对,你不能使用外部表将cta导出到CSV。

这里有几件事你可以尝试。我假设你有一张这样的表:

create table t as 
  select rownum x, sysdate y from dual
  connect by level <= 1000;
复制


SQLcl parallel spool

您可以利用SQLcl中的CSV sql格式以该格式抽出数据。并使用并行提示让许多进程运行您的查询。那么你只需要假脱机输出:

set term off
set feed off
set sqlformat csv
spool out.csv
select /*+ parallel */* from t;
spool off
复制


DIY parallelism with UTL_FILE

您可以使用utl_file构建一个PL/SQL例程,以从表中导出一系列数据:

create or replace procedure csv_unload ( 
  start_id t.x%type, end_id t.x%type
) as
  type t_tab is table of t%rowtype;
  rws  t_tab;
  output   utl_file.file_type;
  filename varchar2(100);
begin

  select * 
  bulk   collect into rws
  from   t
  where  x between start_id and end_id;
  
  filename := 't_' || start_id || '_' || end_id || '.csv';
  
  execute immediate 'alter session set nls_date_format=''YYYY/MM/DD'''; 
  
  output := utl_file.fopen ( 'TMP', filename, 'w' );
  
  utl_file.put ( output, 'X,Y' );
  
  for i in 1 .. rws.count loop
    utl_file.put_line ( output, rws(i).x || ',' || rws(i).y );
  end loop;
  
  utl_file.fclose ( output );
  
end csv_unload;
/
复制


当您导出数百万行时,您可能需要更改批量收集以使用具有限制的显式游标。否则您可能会用完PGA! ;)

然后使用dbms_parallel_execute调用这个这将提交N个作业产生N个文件,你可以合并在一起:

declare
  task  varchar2(30) := 'parallel_unload';
  plsql varchar2(1000);
begin
  dbms_parallel_execute.create_task( task_name => task );
  
  dbms_parallel_execute.create_chunks_by_sql(
    task_name   => task,
    sql_stmt    => 'with grps as (
  select ntile(10) over (order by x) grp, t.*
  from   t
)
  select min(x) start_id, max(x) end_id from grps
  group  by grp',
    by_rowid    => false
  );
   
  plsql := q'[begin 
   csv_unload( :start_id,:end_id );
end;]';

  dbms_parallel_execute.run_task(
      task_name        => task,
      sql_stmt         => plsql,
      language_flag    => dbms_sql.native,
      parallel_level   => 10
  );
  
  dbms_parallel_execute.drop_task( task_name => task );
end;
/
复制


HT to Sean Stuber for PL/SQL dbms_parallel_execute示例:https://seanstuber.wordpress.com/2013/10/17/parallel-plsql-with-dbms_parallel_execute/

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论