收縮表段(shrink space)

收縮表段(shrink space)

2011年07月25日 09:22:26sql

閱讀數:15483數據庫

--====================
-- 收縮表段(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   緩存

 
  1. SQL> col SEGMENT_NAME format a20 性能優化

  2. SQL> select OWNER,SEGMENT_NAME,BYTES/1024/1024,BLOCKS from dba_segments 函數

  3. 2 where owner='SCOTT' and SEGMENT_NAME='BIG_TABLE'; 工具

  4.  
  5. OWNER SEGMENT_NAME BYTES/1024/1024 BLOCKS 性能

  6. ------------------------------ -------------------- --------------- ---------- 優化

  7. SCOTT BIG_TABLE 120 15360 this

  8.  
  9. SQL> select table_name,blocks,empty_blocks from dba_tables spa

  10. 2 where table_name='big_table' and owner='scott'; -->未更新統計信息前BLOCKS,EMPTY_BLOCKS列爲空

  11.  
  12. TABLE_NAME BLOCKS EMPTY_BLOCKS

  13. ------------------------------ ---------- ------------

  14. BIG_TABLE

  15.  
  16. SQL> exec dbms_stats.gather_table_stats(ownname=>'SCOTT',tabname=>'BIG_TABLE',estimate_percent=>30);

  17.  
  18. PL/SQL procedure successfully completed.

  19.  
  20. SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from dba_tables

  21. 2 where TABLE_NAME='BIG_TABLE' and owner='SCOTT';

  22.  
  23. TABLE_NAME BLOCKS EMPTY_BLOCKS

  24. ------------------------------ ---------- ------------

  25. BIG_TABLE 14590 0 -->使用gather_table_stats時不會統計EMPTY_BLOCKS塊

  26.  
  27. SQL> analyze table big_table compute statistics; -->使用analyze更新統計信息後EMPTY_BLOCKS獲得數據

  28.  
  29. Table analyzed.

  30.  
  31. SQL> select TABLE_NAME,BLOCKS,EMPTY_BLOCKS from dba_tables

  32. 2 where TABLE_NAME='BIG_TABLE' and owner='SCOTT';

  33.  
  34. TABLE_NAME BLOCKS EMPTY_BLOCKS

  35. ------------------------------ ---------- ------------

  36. BIG_TABLE 14590 770

  37.  
  38. SQL> set serveroutput on;

  39. SQL> exec show_space('BIG_TABLE','SCOTT'); -->使用show_space過程或的BIG_TABLE上的空間分配信息

  40. Unformatted Blocks ..................... 0

  41. FS1 Blocks (0-25) ...................... 0 -->空閒度爲0-25%的塊數。FS1,FS2,FS3,FS4爲空閒度所佔的百分比

  42. FS2 Blocks (25-50) ..................... 0

  43. FS3 Blocks (50-75) ..................... 0

  44. FS4 Blocks (75-100)..................... 0

  45. Full Blocks ............................ 14,427

  46. Total Blocks............................ 15,360

  47. Total Bytes............................. 125,829,120

  48. Total MBytes............................ 120

  49. Unused Blocks........................... 770

  50. Unused Bytes............................ 6,307,840

  51. Last Used Ext FileId.................... 4

  52. Last Used Ext BlockId................... 16,521

  53. Last Used Block......................... 254

  54.  
  55. PL/SQL procedure successfully completed.

2. 刪除記錄以後,進行收縮表段   

 
  1. SQL> delete from big_table where owner in ('SCOTT','SYSTEM'); -->刪除記錄

  2.  
  3. 8715 rows deleted.

  4.  
  5. SQL> commit;

  6.  
  7. Commit complete.

  8.  
  9. SQL> alter table big_table shrink space; -->實施shrink,提示沒有啓用ROW MOVEMENT

  10. alter table big_table shrink space

  11. *

  12. ERROR at line 1:

  13. ORA-10636: ROW MOVEMENT is not enabled

  14.  
  15. SQL> alter table big_table enable row movement; -->開啓row movement

  16.  
  17. Table altered.

  18.  
  19. SQL> alter table big_table shrink space; -->shrink成功

  20.  
  21. Table altered.

  22.  
  23. SQL> exec show_space('BIG_TABLE','SCOTT'); -->從下面的結果中能夠看到塊數以及總大小已經變小

  24. Unformatted Blocks ..................... 0

  25. FS1 Blocks (0-25) ...................... 1

  26. FS2 Blocks (25-50) ..................... 1

  27. FS3 Blocks (50-75) ..................... 0

  28. FS4 Blocks (75-100)..................... 0

  29. Full Blocks ............................ 14,318

  30. Total Blocks............................ 14,488

  31. Total Bytes............................. 118,685,696

  32. Total MBytes............................ 113

  33. Unused Blocks........................... 5

  34. Unused Bytes............................ 40,960

  35. Last Used Ext FileId.................... 4

  36. Last Used Ext BlockId................... 16,521

  37. Last Used Block......................... 147

  38.  
  39. PL/SQL procedure successfully completed.

3. 驗證cascade與compact的差別   

 
  1. SQL> delete from big_table where rownum<8000; -->再次刪除一些記錄

  2.  
  3. 7999 rows deleted.

  4.  
  5. SQL> alter table big_table shrink space compact; -->使用compact方式收縮表段

  6.  
  7. Table altered.

  8.  
  9. SQL> exec show_space('BIG_TABLE','SCOTT');

  10. Unformatted Blocks ..................... 0

  11. FS1 Blocks (0-25) ...................... 1

  12. FS2 Blocks (25-50) ..................... 2

  13. FS3 Blocks (50-75) ..................... 0

  14. FS4 Blocks (75-100)..................... 103

  15. Full Blocks ............................ 14,214 --僅有的變化爲14318-14214=104塊,即徹底填滿的數據塊減小了104塊

  16. Total Blocks............................ 14,488 --數據的總塊數及總大小並無減小,即未移動高水位線

  17. Total Bytes............................. 118,685,696

  18. Total MBytes............................ 113

  19. Unused Blocks........................... 5

  20. Unused Bytes............................ 40,960

  21. Last Used Ext FileId.................... 4

  22. Last Used Ext BlockId................... 16,521

  23. Last Used Block......................... 147

  24.  
  25. PL/SQL procedure successfully completed.

  26.  
  27. SQL> alter table big_table shrink space cascade; -->使用cascade方式收縮,

  28.  
  29. Table altered.

  30.  
  31. SQL> exec show_space('BIG_TABLE','SCOTT');

  32. Unformatted Blocks ..................... 0

  33. FS1 Blocks (0-25) ...................... 1

  34. FS2 Blocks (25-50) ..................... 2

  35. FS3 Blocks (50-75) ..................... 0

  36. FS4 Blocks (75-100)..................... 0

  37. Full Blocks ............................ 14,214

  38. Total Blocks............................ 14,384 -->總塊數及總大小均已減小

  39. Total Bytes............................. 117,833,728

  40. Total MBytes............................ 112

  41. Unused Blocks........................... 4

  42. Unused Bytes............................ 32,768

  43. Last Used Ext FileId.................... 4

  44. Last Used Ext BlockId................... 16,521

  45. Last Used Block......................... 44

  46.  
  47. PL/SQL procedure successfully completed.

  48.  
  49. -->收縮以後索引依然有效

  50. SQL> select OWNER,INDEX_NAME,STATUS from dba_indexes where TABLE_NAME='BIG_TABLE';

  51.  
  52. OWNER INDEX_NAME STATUS

  53. ------------------------------ ------------------------------ --------

  54. SCOTT BIG_TABLE_PK VALID

5、語法總結:      

 
  1. ALTER TABLE <table_name> ENABLE ROW MOVEMENT -->前提條件

  2.  
  3. ALTER TABLE <table_name> SHRINK SPACE [ <NULL> | COMPACT | CASCADE ];

  4.  
  5. ALTER TABLE <table_name> SHRINK SPACE COMPCAT; -->縮小表和索引,不移動高水位線,不釋放空間

  6.  
  7. ALTER TABLE <table_name> SHRINK SPACE; -->收縮表,下降高水位線;

  8.  
  9. ALTER TABLE <table_name> SHRINK SPACE CASCADE; -->收縮表,下降高水位線,而且相關索引也要收縮一下

  10.  
  11. ALTER TABLE <table_name> MODIFY LOB (lob_column) (SHRINK SPACE); -->收縮LOB段

  12.  
  13. ALTER INDEX IDXNAME SHRINK SPACE; -->索引段的收縮,同表段


6、批量收縮腳本
1. 普通表(根據相應需求修改下面的語句生產相應腳本)   

 
  1. select'alter table '||table_name||' enable row movement;'

  2. ||chr(10)||'alter table '||table_name||' shrink space;'||chr(10)from user_tables;

  3.  
  4. select'alter index '||index_name||' shrink space;'||chr(10)from user_indexes;

2. 分區表的處理

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

    在表上建有函數索引(包括全文索引)會失敗。   

 
  1. --根據相應需求修改下面的語句生產相應腳本

  2. select 'alter table '||owner||'.'||table_name||' enable row movement;'

  3. ||chr(10)||'alter table '||owner||'.'||table_name||' shrink space;'||chr(10) from dba_tables

  4. where owner=upper('&input_owner');

  5.  
  6. select 'alter index '||owner||'.'||index_name||' shrink space;'

  7. ||chr(10) from dba_indexes where uniqueness='NONUNIQUE' ;

  8.  
  9. select 'alter table '||owner||'.'||segment_name||' modify partition '||partition_name||' shrink space;'

  10. ||chr(10) from dba_segments where segment_type='TABLE PARTITION';

 3. 附show_space腳本(來自Tom大師)   

 
  1. CREATE OR REPLACE PROCEDURE show_space

  2. (

  3. p_segname IN VARCHAR2,

  4. p_owner IN VARCHAR2 DEFAULT USER,

  5. p_type IN VARCHAR2 DEFAULT 'TABLE',

  6. p_partition IN VARCHAR2 DEFAULT NULL

  7. )

  8. -- this procedure uses authid current user so it can query DBA_*

  9. -- views using privileges from a ROLE, and so it can be installed

  10. -- once per database, instead of once per user who wanted to use it

  11. AUTHID CURRENT_USER AS

  12. l_free_blks NUMBER;

  13. l_total_blocks NUMBER;

  14. l_total_bytes NUMBER;

  15. l_unused_blocks NUMBER;

  16. l_unused_bytes NUMBER;

  17. l_LastUsedExtFileId NUMBER;

  18. l_LastUsedExtBlockId NUMBER;

  19. l_LAST_USED_BLOCK NUMBER;

  20. l_segment_space_mgmt VARCHAR2(255);

  21. l_unformatted_blocks NUMBER;

  22. l_unformatted_bytes NUMBER;

  23. l_fs1_blocks NUMBER;

  24. l_fs1_bytes NUMBER;

  25. l_fs2_blocks NUMBER;

  26. l_fs2_bytes NUMBER;

  27. l_fs3_blocks NUMBER;

  28. l_fs3_bytes NUMBER;

  29. l_fs4_blocks NUMBER;

  30. l_fs4_bytes NUMBER;

  31. l_full_blocks NUMBER;

  32. l_full_bytes NUMBER;

  33. -- inline procedure to print out numbers nicely formatted

  34. -- with a simple label

  35. PROCEDURE p

  36. (

  37. p_label IN VARCHAR2,

  38. p_num IN NUMBER

  39. ) IS

  40. BEGIN

  41. dbms_output.put_line(rpad(p_label, 40, '.') ||

  42. to_char(p_num, '999,999,999,999'));

  43. END;

  44. BEGIN

  45. -- this query is executed dynamically in order to allow this procedure

  46. -- to be created by a user who has access to DBA_SEGMENTS/TABLESPACES

  47. -- via a role as is customary.

  48. -- NOTE: at runtime, the invoker MUST have access to these two

  49. -- views!

  50. -- this query determines if the object is an ASSM object or not

  51. BEGIN

  52. EXECUTE IMMEDIATE 'select ts.segment_space_management

  53. from dba_segments seg, dba_tablespaces ts

  54. where seg.segment_name = :p_segname

  55. and (:p_partition is null or

  56. seg.partition_name = :p_partition)

  57. and seg.owner = :p_owner

  58. and seg.tablespace_name = ts.tablespace_name'

  59. INTO l_segment_space_mgmt

  60. USING p_segname, p_partition, p_partition, p_owner;

  61. EXCEPTION

  62. WHEN too_many_rows THEN

  63. dbms_output.put_line('This must be a partitioned table, use p_partition => ');

  64. RETURN;

  65. END;

  66. -- if the object is in an ASSM tablespace, we must use this API

  67. -- call to get space information, otherwise we use the FREE_BLOCKS

  68. -- API for the user-managed segments

  69. IF l_segment_space_mgmt = 'AUTO' THEN

  70. dbms_space.space_usage(p_owner,

  71. p_segname,

  72. p_type,

  73. l_unformatted_blocks,

  74. l_unformatted_bytes,

  75. l_fs1_blocks,

  76. l_fs1_bytes,

  77. l_fs2_blocks,

  78. l_fs2_bytes,

  79. l_fs3_blocks,

  80. l_fs3_bytes,

  81. l_fs4_blocks,

  82. l_fs4_bytes,

  83. l_full_blocks,

  84. l_full_bytes,

  85. p_partition);

  86. p('Unformatted Blocks ', l_unformatted_blocks);

  87. p('FS1 Blocks (0-25) ', l_fs1_blocks);

  88. p('FS2 Blocks (25-50) ', l_fs2_blocks);

  89. p('FS3 Blocks (50-75) ', l_fs3_blocks);

  90. p('FS4 Blocks (75-100)', l_fs4_blocks);

  91. p('Full Blocks ', l_full_blocks);

  92. ELSE

  93. dbms_space.free_blocks(segment_owner => p_owner,

  94. segment_name => p_segname,

  95. segment_type => p_type,

  96. freelist_group_id => 0,

  97. free_blks => l_free_blks);

  98. p('Free Blocks', l_free_blks);

  99. END IF;

  100. -- and then the unused space API call to get the rest of the

  101. -- information

  102. dbms_space.unused_space(segment_owner => p_owner,

  103. segment_name => p_segname,

  104. segment_type => p_type,

  105. partition_name => p_partition,

  106. total_blocks => l_total_blocks,

  107. total_bytes => l_total_bytes,

  108. unused_blocks => l_unused_blocks,

  109. unused_bytes => l_unused_bytes,

  110. LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,

  111. LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,

  112. LAST_USED_BLOCK => l_LAST_USED_BLOCK);

  113. p('Total Blocks', l_total_blocks);

  114. p('Total Bytes', l_total_bytes);

  115. p('Total MBytes', trunc(l_total_bytes / 1024 / 1024));

  116. p('Unused Blocks', l_unused_blocks);

  117. p('Unused Bytes', l_unused_bytes);

  118. p('Last Used Ext FileId', l_LastUsedExtFileId);

  119. p('Last Used Ext BlockId', l_LastUsedExtBlockId);

  120. p('Last Used Block', l_LAST_USED_BLOCK);

  121. END;

  122.  

7、快捷參考

 

有關性能優化請參考

    Oracle硬解析與軟解析

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

    Buffercache 的調整與優化(一)

    Oracle表緩存(cachingtable)的使用

 

有關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

相關文章
相關標籤/搜索