隻言片語分析datapump的工作原理

yuntui發表於2016-11-03
datapump是從oracle 10g推出的新的資料匯入匯出工具,可以說是exp/imp的加強版,主要的亮點在於服務端,結合了direct+parallel,而且從datapump的結構上來說也和exp/imp有很大的差別。而老式的exp/imp還有一套自己的資料字典表需要維護,習慣了exp/imp,突然切換到expdp/impdp還有是一些牴觸情緒的,因為從之前的感觸中沒有感受到datapump的強大,從公司的team的反饋,產品線中也遇到了不少的bug.但是很多東西你熟悉了了解了,就會明白oracle設計它的一些原因和出發點,有些小的問題也是可以接受的。
datapump官方沒有提供很多Internal的東西,都只限於操作層面。以下內容都基於個人理解,歡迎拍磚。

一般來說在資料的匯入過程中,oracle會建立3個臨時的表,之前在排查Impdp臨時中斷的問題中注意到了這個細節,但是如何把他們關聯一直沒有頭緒。http://blog.itpub.net/23718752/viewspace-1189257/
IMPORT的表類似下面的形式
SYS_IMPORT_TABLE_28 
ERR的表類似下面的形式。
ERR$DP13FC20810001
ET的表類似下面的形式。
ET$1B5C6DCF0001

如果嘗試訪問這些表ET,ERR,會馬上丟擲ora錯誤,可以看出這些臨時表是基於external table的形式,而且是不對外訪問的,在資料匯入完成之後就會自動清空。
SQL> select *from ET$1B5C6DCF0001;
ERROR:
ORA-29913: error in executing ODCIEXTTABLEOPEN callout
KUP-11024: This external table can only be accessed from within a Data Pump
job.

而且impdp相對Imp有一個特別的優點就是可以隨時檢視匯入的進度。使用Impdp  xxxx attach=SYS_IMPORT_TABLE_28 的形式就可以檢視匯入的資料量,匯入的進度。這些情況基本都是基於SYS_IMPORT_TABLE_28 表來讀取的資訊,它基本就是一個控制表。

而ET,ERR的表是怎麼關聯的呢,直到有一天我檢視一個效能問題的時候,從awr的日誌中發現瞭如下的一段內容,關於datapump的。
Elapsed Time (s) Executions Elapsed Time per Exec (s) %Total %CPU %IO SQL Id SQL Module SQL Text








3,553.36 0   1.01 35.03 10.32 6cz7m51m82vqg Data Pump Worker INSERT /*+ PARALLEL("MO1_MEMO"...

相關的sql如下:
6cz7m51m82vqg INSERT /*+ PARALLEL("TEST_MEMO", 1)+*/ INTO RELATIONAL("APPO"."TEST_MEMO" NOT XMLTYPE) ("APP_ID", "ENTITY_KEY", "PERIOD_KEY", "MEMO_ID", "SYS_CREATION_DATE", "SYS_UPDATE_DATE",xxxxxxxx, "ATTR10VALUE", "CLOB_IND", "MEMO_SYSTEM_TEXT_C") SELECT "APP_ID", "ENTITY_KEY", "PERIOD_KEY", "MEMO_ID", "SYS_CREATION_DATE", "SYS_UPDATE_DATE", xxxxxxxx, "ATTR10VALUE", "CLOB_IND", "MEMO_SYSTEM_TEXT_C" FROM "ET$111D05F70001" KU$ LOG ERRORS INTO "APPO"."ERR$DP111D05F70001" REJECT LIMIT UNLIMITED

可以很清楚的發現原來datapump內部在做這樣的操作
使用Insert select的方式做資料的插入。幾種ET的表是作為中間的資料快取表,而ERR的表則是完全基於oracle的新版本特性,啟用了錯誤日誌。
有了這些資訊也就明白,datapump在資料有衝突的情況下是怎麼快取那些資訊的。這些資訊都被放入了ERR的表中。

 Rejected row #1043:

   column APP_ID: 1000
   column ENTITY_KEY: 1
   column PERIOD_KEY: 2
   column MEMO_ID: 34141901


可能仔細檢視上面的sql語句發現insert select可能不是最好的方式,為什麼不適用insert /*+append*/ select的方式呢,你可以簡單做一個測試就會發現,其實在資料的插入中如果啟用錯誤日誌,再啟用append模式是衝突的。參見:http://blog.itpub.net/23718752/viewspace-1190545/
上面的例子中我匯入資料的表中還有CLOB欄位,儘管在Impdp中指定了parallel,但是在實際的插入中還是並行度為1.

所以基於以上資訊,可以發現parallel的情況也是根據資料的情況來制定的,append的方式在某些情況下速度可能更快,可以根據自己的需要來選擇,甚至手工來完成。
  

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

相關文章