收縮表段(shrink space)

--====================
-- 收縮表段(shrink space)
--====================


1、表的增加方式
    當表被建立後,隨着記錄的不斷插入,組成表的區間會被填滿,若是啓用了自動擴展,則當區間填滿後,會分配新的區間。假定高水
    位線隨着記錄的增長從最左端往右端來移動,當到底部區間的尾端時,則新的區間將會被分配。
    
2、表可收縮的原理
    隨着記錄的增長高水位線不斷的右移,記錄的刪除不會致使高水位線往回(左)移動
    刪除記錄後的空閒空間(高水位線左側)儘管可使用,但其稀疏性致使空間空閒
    注:完整的表掃描所耗費的時間不會由於記錄的減小(刪除)而減小

3、使用 alter table tbname shrink space 來收縮表段
     1. 實現原理
        實質上構造一個新表(在內部表現爲一系列的DML操做,即將副本插入新位置,刪除原來位置的記錄)
        靠近末尾處(右端)數據塊中的記錄往開始處(左端)的空閒空間處移動(DML操做),不會引發DML觸發器
        當全部可能的移動被完成,高水位線將會往左端移動(DDL操做)
        新的高水位線右邊的空閒空間被釋放(DDL操做)
        
     2. 實現前提條件
        必須啓用行記錄轉移(enable row movement)
        僅僅適用於堆表,且位於自動段空間管理的表空間(堆表包括:標準表,分區表,物化視圖容器,物化視圖日誌表)
    
     3. 不能實現收縮的表
        羣集表
        具備LONG類型列的表
        LOB段(儘管表自己能夠被縮小),注,10gR2之後版本支持對LOB段的收縮
        具備基於提交的物化視圖的表(由於禁用了觸發器)
        具備rowid物化視圖的表(由於rowid發生了變化)
        IOT映射表IOT溢出段
        索引基於函數的表
        未啓用行記錄轉移的堆表
        
     4. 段收縮的優勢
        提升緩存利用率,提升OLTP的性能
         減小磁盤I/O,提升訪問速度,節省磁盤空間
         段收縮是在線的,索引在段收縮期間維護,不要求額外的磁盤空間
         
     5. 兩個選項
        cascade:縮小表及其索引,並移動高水位線,釋放空間
        compact:僅僅是縮小表和索引,並不移動高水位線,不釋放空間
        alter table tbname shrink space 至關於帶cascade參數

4、實戰演習

1. 查看須要收縮的表段的基本狀況,此處爲表big_table   
SQL> col SEGMENT_NAME format a20                                                                                       
SQL> select OWNER,SEGMENT_NAME,BYTES/1024/1024,BLOCKS from dba_segments                                                
  2  where owner='SCOTT' and SEGMENT_NAME='BIG_TABLE';                                                                 
                                                                                                                       
OWNER                          SEGMENT_NAME         BYTES/1024/1024     BLOCKS                                         
------------------------------ -------------------- --------------- ----------                                         
SCOTT                          BIG_TABLE                        120      15360                                         
                                                                                                                       
SQL> select table_name,blocks,empty_blocks from dba_tables                                                             
  2  where table_name='big_table' and owner='scott';    -->未更新統計信息前BLOCKS,EMPTY_BLOCKS列爲空                  
                                                                                                                       
TABLE_NAME                         BLOCKS EMPTY_BLOCKS                                                                 
------------------------------ ---------- ------------                                                                 
BIG_TABLE                                                                                                              
                                                                                                                       
SQL> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'BIG_TABLE',estimate_percent=>30);                   
                                                                                                                       
PL/SQL procedure successfully completed.                                                                               
                                                                                                                       
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from dba_tables                                                             
  2  where TABLE_NAME='BIG_TABLE' and owner='SCOTT';                                                                   
                                                                                                                       
TABLE_NAME                         BLOCKS EMPTY_BLOCKS                                                                 
------------------------------ ---------- ------------                                                                 
BIG_TABLE                           14590            0   -->使用gather_table_stats時不會統計EMPTY_BLOCKS塊             
                                                                                                                       
SQL> analyze table big_table compute statistics;         -->使用analyze更新統計信息後EMPTY_BLOCKS獲得數據              
                                                                                                                       
Table analyzed.                                                                                                        
                                                                                                                       
SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from dba_tables                                                             
  2  where TABLE_NAME='BIG_TABLE' and owner='SCOTT';                                                                   
                                                                                                                       
TABLE_NAME                         BLOCKS EMPTY_BLOCKS                                                                 
------------------------------ ---------- ------------                                                                 
BIG_TABLE                           14590          770                                                                 
                                                                                                                       
SQL> set serveroutput on;                                                                                              
SQL> exec show_space('BIG_TABLE','SCOTT');                -->使用show_space過程或的BIG_TABLE上的空間分配信息           
Unformatted Blocks .....................               0                                                               
FS1 Blocks (0-25) ......................               0  -->空閒度爲0-25%的塊數。FS1,FS2,FS3,FS4爲空閒度所佔的百分比  
FS2 Blocks (25-50) .....................               0                                                               
FS3 Blocks (50-75) .....................               0                                                               
FS4 Blocks (75-100).....................               0                                                               
Full Blocks ............................          14,427                                                               
Total Blocks............................          15,360                                                               
Total Bytes.............................     125,829,120                                                               
Total MBytes............................             120                                                               
Unused Blocks...........................             770                                                               
Unused Bytes............................       6,307,840                                                               
Last Used Ext FileId....................               4                                                               
Last Used Ext BlockId...................          16,521                                                               
Last Used Block.........................             254                                                               
                                                                                                                       
PL/SQL procedure successfully completed.
2. 刪除記錄以後,進行收縮表段   
SQL> delete from big_table where owner in ('SCOTT','SYSTEM');   -->刪除記錄                                 
                                                                                                            
8715 rows deleted.                                                                                          
                                                                                                            
SQL> commit;                                                                                                
                                                                                                            
Commit complete.                                                                                            
                                                                                                            
SQL> alter table big_table shrink space;                        -->實施shrink,提示沒有啓用ROW MOVEMENT      
alter table big_table shrink space                                                                          
*                                                                                                           
ERROR at line 1:                                                                                            
ORA-10636: ROW MOVEMENT is not enabled                                                                      
                                                                                                            
SQL> alter table big_table enable row movement;                 -->開啓row movement                         
                                                                                                            
Table altered.                                                                                              
                                                                                                            
SQL> alter table big_table shrink space;                        -->shrink成功                               
                                                                                                            
Table altered.                                                                                              
                                                                                                            
SQL> exec show_space('BIG_TABLE','SCOTT');         -->從下面的結果中能夠看到塊數以及總大小已經變小          
Unformatted Blocks .....................               0                                                    
FS1 Blocks (0-25) ......................               1                                                    
FS2 Blocks (25-50) .....................               1                                                    
FS3 Blocks (50-75) .....................               0                                                    
FS4 Blocks (75-100).....................               0                                                    
Full Blocks ............................          14,318                                                    
Total Blocks............................          14,488                                                    
Total Bytes.............................     118,685,696                                                    
Total MBytes............................             113                                                    
Unused Blocks...........................               5                                                    
Unused Bytes............................          40,960                                                    
Last Used Ext FileId....................               4                                                    
Last Used Ext BlockId...................          16,521                                                    
Last Used Block.........................             147                                                    
                                                                                                            
PL/SQL procedure successfully completed.
3. 驗證cascade與compact的差別   
SQL> delete from big_table where rownum<8000;     -->再次刪除一些記錄                                                
                                                                                                                     
7999 rows deleted.                                                                                                   
                                                                                                                     
SQL> alter table big_table shrink space compact;  -->使用compact方式收縮表段                                         
                                                                                                                     
Table altered.                                                                                                       
                                                                                                                     
SQL> exec show_space('BIG_TABLE','SCOTT');                                                                           
Unformatted Blocks .....................               0                                                             
FS1 Blocks (0-25) ......................               1                                                             
FS2 Blocks (25-50) .....................               2                                                             
FS3 Blocks (50-75) .....................               0                                                             
FS4 Blocks (75-100).....................             103                                                             
Full Blocks ............................          14,214 --僅有的變化爲14318-14214=104塊,即徹底填滿的數據塊減小了104塊
Total Blocks............................          14,488 --數據的總塊數及總大小並無減小,即未移動高水位線          
Total Bytes.............................     118,685,696                                                             
Total MBytes............................             113                                                             
Unused Blocks...........................               5                                                             
Unused Bytes............................          40,960                                                             
Last Used Ext FileId....................               4                                                             
Last Used Ext BlockId...................          16,521                                                             
Last Used Block.........................             147                                                             
                                                                                                                     
PL/SQL procedure successfully completed.                                                                             
                                                                                                                     
SQL> alter table big_table shrink space cascade;  -->使用cascade方式收縮,                                           
                                                                                                                     
Table altered.                                                                                                       
                                                                                                                     
SQL> exec show_space('BIG_TABLE','SCOTT');                                                                           
Unformatted Blocks .....................               0                                                             
FS1 Blocks (0-25) ......................               1                                                             
FS2 Blocks (25-50) .....................               2                                                             
FS3 Blocks (50-75) .....................               0                                                             
FS4 Blocks (75-100).....................               0                                                             
Full Blocks ............................          14,214                                                             
Total Blocks............................          14,384   -->總塊數及總大小均已減小                                 
Total Bytes.............................     117,833,728                                                             
Total MBytes............................             112                                                             
Unused Blocks...........................               4                                                             
Unused Bytes............................          32,768                                                             
Last Used Ext FileId....................               4                                                             
Last Used Ext BlockId...................          16,521                                                             
Last Used Block.........................              44                                                             
                                                                                                                     
PL/SQL procedure successfully completed.                                                                             
                                                                                                                     
-->收縮以後索引依然有效                                                                                              
SQL> select OWNER,INDEX_NAME,STATUS from dba_indexes where TABLE_NAME='BIG_TABLE';                                   
                                                                                                                     
OWNER                          INDEX_NAME                     STATUS                                                 
------------------------------ ------------------------------ --------                                               
SCOTT                          BIG_TABLE_PK                   VALID
5、語法總結:      
ALTER TABLE <table_name> ENABLE ROW MOVEMENT   -->前提條件                                       
                                                                                                 
ALTER TABLE <table_name> SHRINK SPACE [ <NULL> | COMPACT | CASCADE ];                            
                                                                                                 
ALTER TABLE <table_name> SHRINK SPACE COMPCAT;  -->縮小表和索引,不移動高水位線,不釋放空間      
                                                                                                 
ALTER TABLE <table_name> SHRINK SPACE;     -->收縮表,下降高水位線;                              
                                                                                                 
ALTER TABLE <table_name> SHRINK SPACE CASCADE; -->收縮表,下降高水位線,而且相關索引也要收縮一下 
                                                                                                 
ALTER TABLE <table_name> MODIFY LOB (lob_column) (SHRINK SPACE);  -->收縮LOB段                   
                                                                                                 
ALTER INDEX IDXNAME SHRINK SPACE;     -->索引段的收縮,同表段

6、批量收縮腳本
1. 普通表(根據相應需求修改下面的語句生產相應腳本)   
select'alter table '||table_name||' enable row movement;'                        
||chr(10)||'alter table '||table_name||' shrink space;'||chr(10)from user_tables;
                                                                                 
select'alter index '||index_name||' shrink space;'||chr(10)from user_indexes;
2. 分區表的處理

    分區表進行shrink space時發生ORA-10631錯誤.shrink space有一些限制.

    在表上建有函數索引(包括全文索引)會失敗。   
--根據相應需求修改下面的語句生產相應腳本                                                                
select 'alter table '||owner||'.'||table_name||' enable row movement;'                                  
||chr(10)||'alter table '||owner||'.'||table_name||' shrink space;'||chr(10) from dba_tables            
where owner=upper('&input_owner');                                                                      
                                                                                                        
select 'alter index '||owner||'.'||index_name||' shrink space;'                                         
||chr(10) from dba_indexes where uniqueness='NONUNIQUE' ;                                               
                                                                                                        
select 'alter table '||owner||'.'||segment_name||' modify partition '||partition_name||' shrink space;' 
||chr(10) from dba_segments where segment_type='TABLE PARTITION';
  3. 附show_space腳本(來自Tom大師)   
CREATE OR REPLACE PROCEDURE show_space                                                        
(                                                                                             
    p_segname IN VARCHAR2,                                                                    
    p_owner IN VARCHAR2 DEFAULT USER,                                                         
    p_type IN VARCHAR2 DEFAULT 'TABLE',                                                       
    p_partition IN VARCHAR2 DEFAULT NULL                                                      
)                                                                                             
-- this procedure uses authid current user so it can query DBA_*                              
    -- views using privileges from a ROLE, and so it can be installed                         
    -- once per database, instead of once per user who wanted to use it                       
AUTHID CURRENT_USER AS                                                                        
    l_free_blks NUMBER;                                                                       
    l_total_blocks NUMBER;                                                                    
    l_total_bytes NUMBER;                                                                     
    l_unused_blocks NUMBER;                                                                   
    l_unused_bytes NUMBER;                                                                    
    l_LastUsedExtFileId NUMBER;                                                               
    l_LastUsedExtBlockId NUMBER;                                                              
    l_LAST_USED_BLOCK NUMBER;                                                                 
    l_segment_space_mgmt VARCHAR2(255);                                                       
    l_unformatted_blocks NUMBER;                                                              
    l_unformatted_bytes NUMBER;                                                               
    l_fs1_blocks NUMBER;                                                                      
    l_fs1_bytes NUMBER;                                                                       
    l_fs2_blocks NUMBER;                                                                      
    l_fs2_bytes NUMBER;                                                                       
    l_fs3_blocks NUMBER;                                                                      
    l_fs3_bytes NUMBER;                                                                       
    l_fs4_blocks NUMBER;                                                                      
    l_fs4_bytes NUMBER;                                                                       
    l_full_blocks NUMBER;                                                                     
    l_full_bytes NUMBER;                                                                      
    -- inline procedure to print out numbers nicely formatted                                 
    -- with a simple label                                                                    
    PROCEDURE p                                                                               
    (                                                                                         
        p_label IN VARCHAR2,                                                                  
        p_num IN NUMBER                                                                       
    ) IS                                                                                      
    BEGIN                                                                                     
        dbms_output.put_line(rpad(p_label, 40, '.') ||                                        
                             to_char(p_num, '999,999,999,999'));                              
    END;                                                                                      
BEGIN                                                                                         
    -- this query is executed dynamically in order to allow this procedure                    
    -- to be created by a user who has access to DBA_SEGMENTS/TABLESPACES                     
    -- via a role as is customary.                                                            
    -- NOTE: at runtime, the invoker MUST have access to these two                            
    -- views!                                                                                 
    -- this query determines if the object is an ASSM object or not                           
    BEGIN                                                                                     
        EXECUTE IMMEDIATE 'select ts.segment_space_management                                 
from dba_segments seg, dba_tablespaces ts                                                     
where seg.segment_name = :p_segname                                                           
and (:p_partition is null or                                                                  
seg.partition_name = :p_partition)                                                            
and seg.owner = :p_owner                                                                      
and seg.tablespace_name = ts.tablespace_name'                                                 
            INTO l_segment_space_mgmt                                                         
            USING p_segname, p_partition, p_partition, p_owner;                               
    EXCEPTION                                                                                 
        WHEN too_many_rows THEN                                                               
            dbms_output.put_line('This must be a partitioned table, use p_partition => ');    
            RETURN;                                                                           
    END;                                                                                      
    -- if the object is in an ASSM tablespace, we must use this API                           
    -- call to get space information, otherwise we use the FREE_BLOCKS                        
    -- API for the user-managed segments                                                      
    IF l_segment_space_mgmt = 'AUTO' THEN                                                     
        dbms_space.space_usage(p_owner,                                                       
                               p_segname,                                                     
                               p_type,                                                        
                               l_unformatted_blocks,                                          
                               l_unformatted_bytes,                                           
                               l_fs1_blocks,                                                  
                               l_fs1_bytes,                                                   
                               l_fs2_blocks,                                                  
                               l_fs2_bytes,                                                   
                               l_fs3_blocks,                                                  
                               l_fs3_bytes,                                                   
                               l_fs4_blocks,                                                  
                               l_fs4_bytes,                                                   
                               l_full_blocks,                                                 
                               l_full_bytes,                                                  
                               p_partition);                                                  
        p('Unformatted Blocks ', l_unformatted_blocks);                                       
        p('FS1 Blocks (0-25) ', l_fs1_blocks);                                                
        p('FS2 Blocks (25-50) ', l_fs2_blocks);                                               
        p('FS3 Blocks (50-75) ', l_fs3_blocks);                                               
        p('FS4 Blocks (75-100)', l_fs4_blocks);                                               
        p('Full Blocks ', l_full_blocks);                                                     
    ELSE                                                                                      
        dbms_space.free_blocks(segment_owner => p_owner,                                      
                               segment_name => p_segname,                                     
                               segment_type => p_type,                                        
                               freelist_group_id => 0,                                        
                               free_blks => l_free_blks);                                     
        p('Free Blocks', l_free_blks);                                                        
    END IF;                                                                                   
    -- and then the unused space API call to get the rest of the                              
    -- information                                                                            
    dbms_space.unused_space(segment_owner => p_owner,                                         
                            segment_name => p_segname,                                        
                            segment_type => p_type,                                           
                            partition_name => p_partition,                                    
                            total_blocks => l_total_blocks,                                   
                            total_bytes => l_total_bytes,                                     
                            unused_blocks => l_unused_blocks,                                 
                            unused_bytes => l_unused_bytes,                                   
                            LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,                  
                            LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,                
                            LAST_USED_BLOCK => l_LAST_USED_BLOCK);                            
    p('Total Blocks', l_total_blocks);                                                        
    p('Total Bytes', l_total_bytes);                                                          
    p('Total MBytes', trunc(l_total_bytes / 1024 / 1024));                                    
    p('Unused Blocks', l_unused_blocks);                                                      
    p('Unused Bytes', l_unused_bytes);                                                        
    p('Last Used Ext FileId', l_LastUsedExtFileId);                                           
    p('Last Used Ext BlockId', l_LastUsedExtBlockId);                                         
    p('Last Used Block', l_LAST_USED_BLOCK);                                                  
END;

7、快捷參考css

有關性能優化請參考sql

    Oracle硬解析與軟解析數據庫

    共享池的調整與優化(Sharedpool Tuning)緩存

    Buffercache 的調整與優化(一)性能優化

    Oracle表緩存(cachingtable)的使用session

 

有關ORACLE體系結構請參考函數

    Oracle表空間與數據文件工具

    Oracle密碼文件性能

    Oracle參數文件優化

    Oracle聯機重作日誌文件(ONLINE LOG FILE)

    Oracle控制文件(CONTROLFILE)

    Oracle歸檔日誌

    Oracle回滾(ROLLBACK)和撤銷(UNDO)

    Oracle數據庫實例啓動關閉過程

    Oracle10g SGA 的自動化管理

    Oracle實例和Oracle數據庫(Oracle體系結構)

 

有關閃回特性請參考

    Oracle閃回特性(FLASHBACK DATABASE)

    Oracle閃回特性(FLASHBACK DROP & RECYCLEBIN)

    Oracle閃回特性(Flashback Query、FlashbackTable)

    Oracle閃回特性(Flashback Version、Flashback Transaction)

 

有關基於用戶管理的備份和備份恢復的概念請參考

    Oracle冷備份

    Oracle熱備份

    Oracle備份恢復概念

    Oracle實例恢復

    Oracle基於用戶管理恢復的處理(詳細描述了介質恢復及其處理)

    SYSTEM表空間管理及備份恢復

    SYSAUX表空間管理及恢復

 

有關RMAN的備份恢復與管理請參考

    RMAN 概述及其體系結構

    RMAN 配置、監控與管理

    RMAN 備份詳解

    RMAN 還原與恢復

    RMANcatalog 的建立和使用

    基於catalog 建立RMAN存儲腳本

基於catalog 的RMAN 備份與恢復

使用RMAN遷移文件系統數據庫到ASM

    RMAN 備份路徑困惑(使用plus archivelog時)

 

有關ORACLE故障請參考

    ORA-32004的錯誤處理

    ORA-01658錯誤

    CRS-0215錯誤處理

    ORA-00119,ORA-00132 錯誤處理

    又一例SPFILE設置錯誤致使數據庫沒法啓動

    對參數FAST_START_MTTR_TARGET= 0 的誤解及設定

    SPFILE錯誤致使數據庫沒法啓動(ORA-01565)

 

有關ASM請參考

    建立ASM實例及ASM數據庫

    ASM 磁盤、目錄的管理

    使用 ASMCMD 工具管理ASM目錄及文件

 

有關SQL/PLSQL請參考

    SQLPlus經常使用命令

    替代變量與SQL*Plus環境設置

    使用Uniread實現SQLplus翻頁功能

    SQL 基礎-->SELECT 查詢

    SQL 基礎--> NEW_VALUE的使用

    SQL 基礎--> 集合運算(UNION與UNION ALL)

    SQL 基礎--> 經常使用函數

    SQL 基礎--> 視圖(CREATEVIEW)

    SQL 基礎--> 建立和管理表

    SQL 基礎--> 多表查詢

    SQL 基礎--> 過濾和排序

    SQL 基礎--> 子查詢

    SQL 基礎--> 分組與分組函數

    SQL 基礎--> 層次化查詢(STARTBY ... CONNECT BY PRIOR)

    SQL 基礎--> ROLLUP與CUBE運算符實現數據彙總

    PL/SQL--> 遊標

    PL/SQL--> 異常處理(Exception)

    PL/SQL--> 語言基礎

    PL/SQL--> 流程控制

    PL/SQL--> PL/SQL記錄

    PL/SQL--> 包的建立與管理

    PL/SQL--> 隱式遊標(SQL%FOUND)

    PL/SQL--> 包重載、初始化

    PL/SQL--> DBMS_DDL包的使用

    PL/SQL--> DML 觸發器

    PL/SQL--> INSTEAD OF 觸發器

    PL/SQL--> 存儲過程

    PL/SQL--> 函數

    PL/SQL--> 動態SQL

    PL/SQL--> 動態SQL的常見錯誤

 

有關ORACLE其它特性

    Oracle經常使用目錄結構(10g)

    使用OEM,SQL*Plus,iSQL*Plus 管理Oracle實例

    日誌記錄模式(LOGGING、FORCE LOGGING 、NOLOGGING)

    表段、索引段上的LOGGING與NOLOGGING

    OralceOMF 功能詳解

    Oracle用戶、對象權限、系統權限  

    Oracle角色、配置文件

    Oracle分區表

    Oracle外部表

    使用外部表管理Oracle 告警日誌(ALAERT_$SID.LOG)

    簇表及簇表管理(Index clustered tables)

    數據泵 EXPDP 導出工具的使用

    數據泵 IMPDP 導入工具的使用

    導入導出 Oracle 分區表數據

    SQL*Loader使用方法

    啓用用戶進程跟蹤

    配置非默認端口的動態服務註冊

    配置ORACLE 客戶端鏈接到數據庫

    systemsys,sysoper sysdba 的區別

    ORACLE_SID、DB_NAME、INSTANCE_NAME、DB_DOMIAN、GLOBAL_NAME

    Oracle補丁全集 (Oracle 9i 10g 11g Path)

    Oracle10.2.0.1 升級到10.2.0.4

    Oracle完全 kill session




          



原文連接: http://blog.csdn.net/robinson_0612/article/details/6630673
相關文章
相關標籤/搜索