Skip to Main Content
  • Questions
  • Fast extract from oracle to TEXT/CSV file

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, %D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B9.

Asked: June 07, 2017 - 4:12 pm UTC

Last updated: June 21, 2017 - 2:18 am UTC

Version: 11.2

Viewed 50K+ times! This question is

You Asked

Hi Oracle Gurus!
We have encountered strange speed issue and need your assistance...

Setting:
1) Oracle 11.2 Exadata machine, 4 nodes,

2) several linux servers which need large amounts of data (10-s of gigabytes) from Oracle extracted to text files

3) average speed of creating text files by SELECTing one table partition from Oracle and saving to text (sqlplus spool or handmade jdbc utility - no difference) on linux servers is 5 Mbytes/sec (40 Mbit/sec), while Ethernet capability is 10x larger (tested by simple file transfer between servers).

4) Create table as select on that 'one table partition' (7 Gb) is executed inside oracle in several seconds - so it is not oracle disk speed issue.

Questions:
1) how to identify the cause of such slow speed (sql*net?!) and what to do to increase it?

2) is there some recommended fast way to extract large amounts to txt files?
maybe in parallel (how)?

3) here
https://asktom.oracle.com/pls/apex/f?p=100:11:::NO::P11_QUESTION_ID:88212348059
is Tom's answer about fast export:

you want speed -- use a little c.

here:

http://asktom.oracle.com/~tkyte/flat/index.html

you'll find in order of speed:

utl_file (slowest but really handy when it is "fast enough")
sqlplus
C

but the link mentioned does not work... what was the answer?

this? http://tkyte.blogspot.ru/2009/10/httpasktomoraclecomtkyteflat.html

export to SYLK
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:728625409049

pro*C
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:459020243348


4) here https://jonathanlewis.wordpress.com/2010/05/07/sqlnet-compression/
is a discussion about sql*net compression with good results.
where to find documentation and guidelines to use it properly on wide tables (more than 1 column) and is it usable with jdbc?

Thanx in advance!

and Connor said...

You can get the pro*c program here

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:459020243348

but to see if its SQLNet, you can do the following:

Run sqlplus on one of the exadata db nodes and spool locally. And experiment with the settings to find what works best. For example:

select systimestamp from dual;
set termout off
set arraysize 1000
set rowprefetch 2
set pages 0
set trimspool on
spool c:\temp\test.out
select * from ...
spool off
set termout on
select systimestamp from dual;

On my laptop, that lets me unload 25million rows (~3GB) in around 3mins, whereas I can do a full scan of the table in just a few seconds. So there is obviously a cpu and filesystem IO cost to formatting and spooling results.

As long as your filesystem and network support it, probably the best way would be parallel jobs. For example, I ran the same test above in 3 concurrent streams, each one still takes 3mins...which means I can actually unload 75million rows (9G) in 3mins.

Sorting the output should give some de-dup benefit, and hence reduce network traffic, but I suspect it might be the file formatting/writing time where the biggest gains can be made.

Rating

  (3 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Alex, June 08, 2017 - 10:15 am UTC

Connor, thanx a lot!
could you provide some explanation for these points, please:

1)
>So there is obviously a cpu and filesystem IO cost to formatting and spooling results
> I suspect it might be the file formatting/writing time where the biggest gains can be made.

could you propose a test case with measurable results which can clearly prove that suspect, e.g.:

oracle reads a table XX seconds with YY CPU (fast)
sql*net transfers results XX seconds with YY CPU (fast)
...
client (e.g. sql*plus) uses YY CPU & ZZ fileIO *and is slow* - here is bottleneck

or there is nothing better measured than simple "run several sql*plus spools simultaneously", which you've done?


2) do I understand correctly that Pro*C program is the "fastest known file extractor to text" for Oracle?

what about CTAS to external table (datapump)?
where it goes in range of:

- utl_file (slowest but really handy when it is "fast enough")
- sqlplus
- C

3) may the extract of one table (any rowsource) be done in parallel with some automatic director without the need to rewrite query?
how?
AFAIK there was some trick with (pipelined?) function to run several sessions on same source table but "take only that rows which correspond to session depending on number of parallel sessions requested"


4) about sql*net compression -
where to find documentation and guidelines to use it properly on wide tables (more than 1 column) and is it usable with jdbc?


Connor McDonald
June 14, 2017 - 3:58 am UTC

"could you propose a test case with measurable results"

Time the following

a) plsql loop

for i in ( select * from my_table ) loop
  null;
end loop;


so you are cycling through the data, still getting the row information but doing nothing with it.

b) sqlplus on the server

set feedback only
set arraysize 500
select * from my_table;

so you are cycling through the data, getting the row information, constructing rows on the client, but not rendering/spooling it.

c) sqlplus on a client

set feedback only
set arraysize 500
select * from my_table;

Same as (b) but you're pulling stuff across a network

d) sqlplus on server

(in a script)
set termout off
set arraysize 500
spool data.out
select * from my_table;
spool off

So now you're constructing rows and spooling them out.

So you can easily play with the various permutations.

The reason I'd expect a pro*c app to be better is that sqlplus is of course "all things to all people", ie, its much more than a "file unload" tool, so there's a lot more code path to travel. A pro*c custom written app can be tailored to do exactly what is required and no more.

%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B9 %D0%A8%D1%83%D1%80%D0%B0%D0%BD, June 19, 2017 - 7:47 am UTC

Connor, thanx a lot for reply!
You still has not answered on these points:

2) what about CTAS to external table (datapump)?
where it goes in range of:

- utl_file (slowest but really handy when it is "fast enough")
- sqlplus
- C (fastest known)

3) may the extract of one table (any rowsource) be done in parallel with some automatic director without the need to rewrite query?
how?
AFAIK there was some trick with (pipelined?) function to run several sessions on same source table but "take only that rows which correspond to session depending on number of parallel sessions requested"


4) about sql*net compression -
where to find documentation and guidelines to use it properly on wide tables (more than 1 column) and is it usable with jdbc?
Connor McDonald
June 21, 2017 - 2:18 am UTC

2) what about CTAS to external table (datapump)?

"several linux servers which need large amounts of data (10-s of gigabytes) from Oracle extracted to text files"

I'm interpreting this as plain text, which takes datapump files out of play.

3) dbms_parallel_execute could be used.

4) it's intention is predominantly for low bandwidth networks

http://www.oracle.com/technetwork/database/enterprise-edition/advancednetworkcompression-2141325.pdf

WHY NOT TO TRACE?

%D0%A1%D0%B5%D1%80%D0%B3%D0%B5%D0%B9 %D0%A8%D1%83%D1%80%D0%B0%D0%BD, June 19, 2017 - 10:36 am UTC

Connor, one more question in addition to previous post: why you didn't mention using TRACE in finding the bottleneck?

for example, if TKPROF shows the following:

Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  resmgr:pq queued                                1        0.00          0.00
  os thread startup                              32        0.17          3.52
  latch free                                      3        0.00          0.00
  PX Deq: Join ACK                               32        0.01          0.01
  PX Deq: Parse Reply                            32        0.01          0.02
  SQL*Net message to client                 1044264        0.00         11.01
  PX Deq: Execute Reply                      273951        0.06         10.22
  SQL*Net message from client               1044264        1.25       3496.23
  SQL*Net more data to client                    10        0.00          0.00
  resmgr:internal state change                    2        0.10          0.20
  PX Deq: Signal ACK RSG                         32        0.00          0.00
  PX Deq: Signal ACK EXT                         32        0.00          0.00
  PX Deq: Slave Session Stats                    32        0.00          0.00
********************************************************************************

 


doesn't this CLEARLY and INSTANTLY mean that most of time is spent OUTSIDE the database , as Tom mentioned here:

https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1154234872764#1639863671441

"Say you are running a pro*c app you wrote, its a batch program. Its taking too long to run. You look and see that the sql*net message from client is HUGE -- guess what that means. In this case, it means the database is not the bottleneck, its spent alot of time WAITING for you to tell it to do something. In this case, this is a non-idle condition, we were not idle (as an entire process -- client+database)....

"