批量匯出csv檔案的基本嘗試

jeanron100發表於2016-03-20
   開發同學前幾天給我提了一個資料查詢的需求,大體是查詢某個表的資料,然後把查詢結果以csv的形式提供給他們,一般來說這種定製查詢,開發的同學都會提供好語句,DBA同學只需要簡單執行即可。
   每次看到語句,我都要簡單評估一下,今天的語句看起來非常簡單,需要在一個歷史庫中進行資料查取,從開發同學提供的語句來看,這個查詢看起來真不簡單。提供的資料都是近5年內的歷史資料,所以我簡單看了下,這個表有10億的記錄,而符合條件的資料就有1億多條。從資料量來看,這個我是真沒法提供了,資料結果集就肯定幾十上百G了,發給開發同學肯定不現實的,而且就算這個坎能邁過去,他們也沒法用啊,一個幾十G的檔案,本地幾十M的檔案excel開啟都成問題,何況這麼大的資料量。
   所以找到開發同學,想了解一下他們要拿這麼多資料幹嘛,需求的情況是怎麼樣的,簡單聊了下,發現原來是資料倉儲組的同事需要做大資料分析,發現以前的部分資料存在問題,所以希望DBA能夠提供一些幫助,把存在問題的歷史資料提供給他們,重新更新一下,所以按照這種情況,這個需求看起來似乎也是合理的了。大資料所需,DBA提供基礎資料。
    所以一個很明顯的問題擺在我面前,那就是如何高效的匯出這部分資料,目前在這種異構的環境中,csv也是一個合理的一種方式,不過大資料部分的同事有個要求就是,因為大資料分析的需要,其實還是希望把這部分資料能夠切分成多個檔案,如果能夠切分到天就最好了,他們就會有針對性的做一些處理。
   對我來說,還需要簡單確認,以前把資料分片,切分以前也寫過一個簡單的工具,不過是在oracle之間的做匯出比較給力,在這個場景裡面需要馬上滿足他們的需求還是有些難度。
所以我簡單分析了一下這個歷史表的情況,可以拍著胸脯給他們肯定的答覆了,按天是可以支援的,因為這個分割槽表就是按照日期進行分割槽的,每天都會有一個單獨的分割槽。
有了這些資訊,我就風風火火開始了資料匯出。
   當前的環境有100多G的空餘空間,感覺應該是夠了,所以就寫了下面兩個指令碼。ora_exp.sh,ora_csv.sh
ora_exp.sh會呼叫ora_csv.sh ,ora_csv.sh的作用就是把資料通過sqlplus的spool方式把資料以分割槽的粒度進行匯出。

date=`date -d "+0 day $1" +%Y%m%d`
enddate=`date -d "+1 day $2" +%Y%m%d`

echo "------------------------------"
echo "date=$date"
echo "enddate=$enddate"
echo "------------------------------"

while [[ $date < $enddate  ]]
do
  echo $date
  sh ora_csv.sh $date  > test_server_log_$date  &
  date=`date -d "+1 day $date" +%Y%m%d`
done

ora_csv.sh的指令碼內容如下:
sqlplus  -s / as sysdba <<eof
set pages 0
set feedback off
set echo off
set trimout on  
set trimspool on
set linesize 500
set headsep off
select
 ID             ||','||
 SN             ||','||
 GROUP_ID       ||','||
 SERVER_IP      ||','||
 SERVER_NAME    ||','||
 ....
 CLIENT_STYLE    csv_col
from test.test_server_log partition (SERVER_LOG_$1) ;
EOF
這個指令碼一旦執行,就會同時開啟多個匯出的session,每個分割槽都會有一個獨立的session來匯出相應的資料,分割槽的命名也是規範的,這就為匯出提供了很大的便利。
比如匯出2011年8月2日到2012年10月1日的資料,就可以這樣執行指令碼
sh ora_exp.sh 2011-08-29  2012-10-01
但是第一次匯出的時候,為了省事,給了一個較大的時間範圍,結果同時上百個session匯出,風風火火,速度確實還是很快,但是馬上碰到的問題就是空間開始告緊。
儘管自己也刪除了部分的資料,但是最後還是有一部分的匯出失敗,總體的感覺就是這種方式看起來還是比較快,但是不太可控,尤其某一個小的環境出問題還是不太好定位。
所以吸取了經驗,調整了時間範圍,把它切分為多個時間段,匯出的檔案馬上壓縮,按照測試的資料來看3G的檔案壓縮後大概在500M,壓縮比還是比較理想的,按照這種情況就需要簡單評估最多需要開啟多少個並行的匯出session了。
以一個dump最大3G的標準,壓縮比為500G,有100G的剩餘空間,那就是100/3.5總體能夠開啟30個並行的session了。
所以按照這個基本的思路,就在ora_exp.sh指令碼中加入了壓縮的部分。每個時間段都是序列執行。
date=`date -d "+0 day $1" +%Y%m%d`
enddate=`date -d "+1 day $2" +%Y%m%d`

echo "------------------------------"
echo "date=$date"
echo "enddate=$enddate"
echo "------------------------------"

while [[ $date < $enddate  ]]
do
  echo $date
  sh ora_csv.sh $date  >test_server_log_$date
  gzip test_server_log_$date
  date=`date -d "+1 day $date" +%Y%m%d`

done
按照這個思路匯出之後。在個把小時過後,終於告一段落,一看壓縮後的檔案有近69G,按照壓縮比,源資料應該有400多G,這種方式還是比較理性的。
[oracle@statg data_split]$ du -sh .
69G

</eof

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/23718752/viewspace-2060567/,如需轉載,請註明出處,否則將追究法律責任。

相關文章