23.1、說明:
1、
眾所周知,在清空表內所有數據時,truncate比delete要快很多,原因是,delete語句每次刪除一行,都在事務日志中為所刪除的每行記錄一項。
truncate通過釋放存儲表數據所用的數據頁來刪除數據,並且只在事務日志中記錄頁的釋放。但是如果表存在外鍵的話,是不能使用truncate的。
在使用的過程中,我發現某個存在外鍵的表,使用truncate提示成功了。一開始,我在懷疑是不是oracle存在bug,在某個特定條件下,觸發了
這個bug,造成truncate成功了。后來,等這張表插入過數據之后,我再使用truncate時,提示失敗了。我這才恍然大悟,這個問題跟exp空表
無法導出是一個原因。oralce11g為了節省存儲空間,新建表的時候默認是不分配segment的。既然segment都沒有,就不用談exp和truncate了。
但是oracle還是預留了系統參數 DEFERRED_SEGMENT_CREATION(延遲創建segment)。這個參數,默認是true。我們可以將他改成false。這
樣的話,再創建表的時候就會立即分配segment了。但是修改參數之前創建的表還是不會立即分配segment的。如果想分配segment,可以在表中
插入一條數據,再刪除。也可以使用 alter table XXX allocate extent,這樣就會創建segment了,再使用exp就會導出空表,而且存在外鍵的表
使用truncate清空數據時,也不會提示成功了。如果單表插入數據后被truncate,則會保留segment。
2、DEFERRED_SEGMENT_CREATION 設置為true的優缺點:
(1)優點:
在創建一系列表的時候,若事先已知許多表並沒有數據,可以指定這個參數為true,這樣可以節省空間,也可以增加建表速度。
(2)缺點:
使用exp導出的時候,不會導出沒有segment分配的表。使用expdp可以導出空表。
3、查看該參數當前設置:
show parameter deferred_segment_creation;
4、修改該參數當前設置:
這個參數可以動態修改,使用 alter system/session set deferred_segment_creation=true/false;
更改后,之前延遲分配segment的表並不會受到影響,仍然為空表。
5、查詢某schema中所有未分配segment的表可以使用以下語句:
select * from user_tables where segment_created = 'NO';
6、若想為這些未分配segment的表分配空間,可以使用語句:
select 'alter table' || table_name || 'allocate extent;' from user_tables where segment_created = 'NO';
為所有空表分配segment,之后就可以進行exp導出了。
23.2、示例:
1、說明:
用impdp命令將從linux(版本:Oracle Database 11g Enterprise Edition Release 11.2.0.4.0-64bit Production,A庫)上面導出的數據庫
導入到本地windows系統的數據庫(Oracle Database 11g Standard Edition Release 11.2.0.1.0 - 64bit Production,B庫)上時,報了以
下錯誤:
錯誤描述:
ORA-00439 未啟用的功能:DEFERRED_SEGMENT_CREATION
或者叫做
ORA-00439 feature not enabled deferred segment creation
2、解決思路:
(1)查看 DEFERRED_SEGMENT_CREATION 參數設置是否一樣:
在A庫查詢參數被設置為TRUE,在B庫查詢參數被設置為FALSE,修改B庫設置,改成 TRUE,重新導入,還是報一樣的錯誤。
(2)查看數據庫版本:
A庫是企業版,B庫是標准版。
DEFERRED_SEGMENT_CREATION 在標准版中不支持該功能。
(3)解決辦法:
在做expdp時,帶上參數 version = 10.2.0,同樣,在做impdp時,也帶上參數 version = 10.2.0。
特別注意:version=11.2.0 是不行的。