oracle匯出多CSV檔案的靠譜的

來源:互聯網
上載者:User

標籤:term   執行   test   命令   head   好的   get   feed   add   

oracle匯出多CSV檔案的問題


----------------------------------------------------------------------

用ksh指令碼從oracle資料庫中匯出80w資料到csv檔案,如使用者給定名字為a.csv(檔案最大4000行記錄),則自動生產檔案為a_1.csv,a_2.csv,...., a_200.csv

我已經實現了一個方法,但80w要導5小時,使用者沒法接受。如下:
sqlplus -s user/pwd @${SqlDir}/select_log.sql >/tmp/a.tmp
然後每read 4000行到檔案a_1.csv,並且每隔4000行換一個檔案名稱。

大家有什麼好方法嗎?注意效率

----------------------------------------------------------------------

先一次性產生一個csv檔案
再用split分割檔案

--------------------------------------------------------

完全贊同樓上說的。

關於效能問題,用oracle spool出80萬行紀錄是非常快的,我剛試了一下,再hp-ux下,spool出某表中100萬紀錄(2列)耗時大約2分鐘,輸出檔案80m, 用split命令分割為每個4000行的檔案耗時數秒而已。 下附測試代碼:

/* sql file:  spool_test.sql */
set pages 0
set head off
set echo off
set feedback off
spool spool_text.csv
select col1, col2 from my_table where rownum<1000000;
spool off
exit

## shell script to spool out:
sqlplus -s user/password @spool_test.sql > /dev/null

## split file:
split -l 4000 spool_text.csv splited


--------------------------------------------------------

export.sh

#Generate the sql language
echo "SET HEADING OFF;">${SqlDir}/select_log.sql
echo "SET FEEDBACK OFF;">>${SqlDir}/select_log.sql
echo "SET LINESIZE 10000;">>${SqlDir}/select_log.sql
echo "SPOOL ${SqlDir}/EXPORT_ALL.CSV;" >> ${SqlDir}/select_log.sql
echo "SELECT SALESMAN_ID||‘,‘||">>${SqlDir}/select_log.sql
echo "SALESMAN_NAME||‘,‘||">>${SqlDir}/select_log.sql
echo "SALES_AMOUNT||‘,‘||">>${SqlDir}/select_log.sql
echo "SALES_DATE from sales_range;">>${SqlDir}/select_log.sql
echo "SPOOL OFF;" >> ${SqlDir}/select_log.sql
echo exit | ${ORACLE_HOME}/bin/sqlplus -s omc_sbardz812/omc_sbardz812 @${SqlDir}
/select_log.sql >/dev/null

split -l 4000 -a 5 ${SqlDir}/EXPORT_ALL.CSV log_20060606_
=============================================================

以上是我的指令碼,80w資料我用了3個多小時還沒完呢。有問題嗎?
另外,很重要的一點,split後,再不是csv尾碼了。看來還得檔案遍曆,然後一個一個的mv 成csv檔案。



--------------------------------------------------------

先整個匯出罷,然後在處理

--------------------------------------------------------

你的代碼看起來沒有問題,但80萬條記錄導3小時沒完成很難讓人理解。

你用sqlplus做一下測試,比如匯出10000條記錄需要多少時間,如果確實很慢,那可能是串連太慢(網路速度?)。

--------------------------------------------------------

匯出為csv檔案很快,就幾分鐘而已,但是split要花3個小時,共250個檔案,每個檔案4000行。我的機器是SUN Blade 150,還有我在server上啟動並執行,不存在網路速度的問題。

--------------------------------------------------------

根據需要匯出的列,單獨建個暫存資料表,比如:create table sales_range_tmp as select salesman_id,salesman_name,sales_amount,sales_date from sales;
再利用指令碼匯出來,看看速度應該有所提高。不過有一點必須明白,全掃描8w的表資料肯定不是幾分鐘可以完成的,何況要寫成物理檔案。


--------------------------------------------------------

KingSunSha(弱水三千),我用spool匯出的檔案大小為9G(8900828448byte on solaris),而你的才80M

--------------------------------------------------------

SELECT 中不要拼接字串,非常影響速度

--------------------------------------------------------

大家還有好的辦法嗎?

--------------------------------------------------------

9GB = 9,216 MB = 9,437,184 KB = 9,663,676,416 Bytes
800,000 records
size of each record (line) = 9GB/800,000 = 12,079 Bytes

select 中只有 4 列(SALESMAN_ID, SALESMAN_NAME, SALES_AMOUNT, SALES_DATE
),你覺得每行紀錄佔12KB合理嗎?

--------------------------------------------------------

問題是你在sqlplus中用了set linesize=100000,所以每行都會spool出100000bytes。
解決這個問題很簡單,在spool開始之前加上兩行set命令

set trimspool on
set termout off

第一個set是指定trim spool出的每行在行末的空格
第二個set是指定只spool而不回顯,所以在運行sqlplus的時候不需要 >/dev/null。


--------------------------------------------------------

非常感謝KingSunSha(弱水三千),現在我把linesize改為100,非常快,2分鐘就完成了。太好了。不過還有一個問題,匯出的檔案,每隔13行就會自動化佈建一個空行,能把這個去掉嗎?因為我匯出的檔案會被我的程式開啟的。

--------------------------------------------------------

just add 
set pagesize 0
before spool to suppress all headings, page breaks, titles, the initial blank line, and other formatting information.


--------------------------------------------------------

just add
set pagesize 0
before spool to suppress all headings, page breaks, titles, the initial blank line, and other formatting information.

--------------------------------------------------------

非常感謝KingSunSha(弱水三千),搞定了,貼出來吧,共用!

echo "SET HEADING OFF;">${SqlDir}/select_log.sql 
echo "SET FEEDBACK OFF;">>${SqlDir}/select_log.sql 
echo "SET LINESIZE 500;">>${SqlDir}/select_log.sql 
echo "SET trimspool on;">>${SqlDir}/select_log.sql 
echo "SET termout off;" >>${SqlDir}/select_log.sql 
echo "SET NEWPAGE NONE;" >>${SqlDir}/select_log.sql 
echo "SPOOL ${SqlDir}/EXPORT_ALL.CSV;" >> ${SqlDir}/select_log.sql 
echo "SELECT SALESMAN_ID||‘,‘||">>${SqlDir}/select_log.sql 
echo "SALESMAN_NAME||‘,‘||">>${SqlDir}/select_log.sql 
echo "SALES_AMOUNT||‘,‘||">>${SqlDir}/select_log.sql 
echo "SALES_DATE from sales_range;">>${SqlDir}/select_log.sql 
echo "SPOOL OFF;" >> ${SqlDir}/select_log.sql 
echo exit | ${ORACLE_HOME}/bin/sqlplus -s user/pwd @${SqlDir}/select_log.sql 

split -l 4000 -a 3 ${SqlDir}/EXPORT_ALL.CSV log_20060606_ 

#mv these splitted file to be csv file 
for file in $(ls ./) 
do 
    echo $file | grep log_20060606_ > /dev/null 
    status=$? 
    if [ $status -eq 0 ]; then 
        mv $file $file.csv 
    fi 
    status=1 
done 

80萬10分鐘就可以搞定了。

ksh可以執行,由於有這句:$(ls ./),sh不支援。

--------------------------------------------------------

謝謝大家!

 

http://blog.csdn.net/studyvcmfc/article/details/7047986

 

oracle匯出多CSV檔案的靠譜的

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.