溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

索引碎片整理--重建索引、合并索引、shrink索引

發(fā)布時間:2020-08-05 07:46:14 來源:ITPUB博客 閱讀:406 作者:mahanso 欄目:關(guān)系型數(shù)據(jù)庫

隨著時間的推移,索引也可能會產(chǎn)生碎片,oracle在處理該問題的時候提供給予我們有三種方式:重建索引、合并索引、shrink 索引。每種都有自己的特點,今天我在此學習一下記錄一下筆記。
第一:重建索引:
  重建索引其實語句很簡單實用alter index index_name rebuild;參數(shù)即可對指定的索引進行重建,但是注意在重建索引的時候 會對相應的對象加鎖,因此重建的時候一定要注意,如何避免在重建索引的時候不影響其他業(yè)務使用呢?那么可以指定online 參數(shù),如:alter index index_name rebuild online;指定該參數(shù)之后就不會對其他業(yè)務訪問對象產(chǎn)生任何影響。另外有時候我們還可以指定并行創(chuàng)建索引,但要注意在指定parallel(degree interger)參數(shù)的時候,那么并行度將存儲于索引中,隨著在基于硬件如cpu個數(shù)創(chuàng)建速度上確實提高了,但在在執(zhí)行查詢的時候?qū)⑹褂貌⑿蟹绞?,有時候也會伴隨著等待事件的出現(xiàn)如:PX Deq Credit: send blkd,因此創(chuàng)建索引是不是應該使用paralle應該斟酌一下。
eg:

[sql] view plain copy
  1. SQL> create index emp_idx1 on emp(empno) parallel (degree 8);  
  2.   
  3. Index created.  
  4.   
  5. SQL> select index_name,degree from user_indexes where table_name='EMP';  
  6.   
  7. INDEX_NAME           DEGREE  
  8. -------------------- ----------------------------------------  
  9. EMP_IDX1             8  


  另外當我們需要重新創(chuàng)建反向鍵索引的時候需要指定reserver參數(shù):alter index index_name rebuild reverse;回收未使用的空間,當使用
alter index index_name deallocate unused;
命令的時候,會將沒有使用的空閑段返回給數(shù)據(jù),但是曾經(jīng)使用過的空塊將不會返還給數(shù)據(jù)庫空間(包含之前刪除的索引或是移動條目導致段內(nèi)沒有使用的空間)對于分區(qū)索引和索引組織表的信息查看:
http://blog.csdn.net/rhys_oracle/article/details/18671897
http://blog.csdn.net/rhys_oracle/article/details/18409063
  另外如何確定是否需要重建索引呢?一般認為有兩種情況:
  1、索引深度大于等于4
  2、已刪除的索引條目占總索引條目的20%
  3、索引空間使用率小于50%
再次不得不提 一個視圖index_stats該視圖默認是沒有任何數(shù)據(jù)的,當使用analyze index index_name validate structure;對索引結(jié)構(gòu)分析之后將會填充相應的數(shù)據(jù),一般該視圖可以提供給我們足夠的信息去引導我們是否需要對索引進行重建。
查看相關(guān)字段信息:

[sql] view plain copy
  1. SQL> desc index_stats;  
  2.  Name                                      Null?    Type  
  3.  ----------------------------------------- -------- ----------------------------  
  4.  HEIGHT                                             NUMBER  (代表索引高度)  
  5.  BLOCKS                                             NUMBER  (索引占用塊數(shù))  
  6.  NAME                                               VARCHAR2(30)(索引名字)  
  7.  PARTITION_NAME                                     VARCHAR2(30)(分區(qū)索引名字)  
  8.  LF_ROWS                                            NUMBER (葉子行數(shù))  
  9.  LF_BLKS                                            NUMBER  (在b樹索引中葉子的塊數(shù))  
  10.  LF_ROWS_LEN                                        NUMBER  (所有葉子行數(shù)的長度)  
  11.  LF_BLK_LEN                                         NUMBER  (在一片葉子中可用空間)  
  12.  BR_ROWS                                            NUMBER  (在B樹索引中有多少個分支行)  
  13.  BR_BLKS                                            NUMBER  (在B樹索引中有多少個分支塊)  
  14.  BR_ROWS_LEN                                        NUMBER  (在B樹索引中所有分支塊的總長度)  
  15.  BR_BLK_LEN                                         NUMBER  (在分支快中可用的空間)  
  16.  DEL_LF_ROWS                                        NUMBER  (在索引中刪除葉子行數(shù))  
  17.  DEL_LF_ROWS_LEN                                    NUMBER  (在索引中刪除葉子行數(shù)的總的長度)  
  18.  DISTINCT_KEYS                                      NUMBER  (唯一值數(shù)目包括刪除的行)  
  19.  MOST_REPEATED_KEY                                  NUMBER  
  20.  BTREE_SPACE                                        NUMBER  (當前分給該 索引總的大小空間)  
  21.  USED_SPACE                                         NUMBER  (已經(jīng)被索引使用的空間大小包含被刪的行數(shù)空間)  
  22.  PCT_USED                                           NUMBER  (索引空間使用率)  
  23.  ROWS_PER_KEY                                       NUMBER  (每個不同鍵值的平均行數(shù)不包括刪除行)  
  24.  BLKS_GETS_PER_ACCESS                               NUMBER    
  25.  PRE_ROWS                                           NUMBER  (前綴行數(shù))  
  26.  PRE_ROWS_LEN                                       NUMBER  (前綴行的總長度)  
  27.  OPT_CMPR_COUNT                                     NUMBER  (壓縮長度)  
  28.  OPT_CMPR_PCTSAVE                                   NUMBER  
  29.   
  30. SQL>   


查看未刪除葉子行數(shù)占總行數(shù)的百分比公式為:((lf_rows-del_lf_rows)/lf_rows)*100;
查看未刪除行占用的空間百分比公式為:((used_space-del_lf_rows_len)/btree_space)*100;
pct_used計算公式為:(used_space/btree_space)*100
eg:

[sql] view plain copy
  1. SQL> create table test as select rownum id,'Amy' text from dual connect by level<=10000;  
  2.   
  3. Table created.  
  4.   
  5. SQL> select count(*) from test;  
  6.   
  7.   COUNT(*)  
  8. ----------  
  9.      10000  
  10.   
  11. SQL> create index test_idx1 on test(id);  
  12.   
  13. Index created.  
  14.   
  15. SQL> select * from index_stats;  
  16.   
  17. no rows selected  
  18.   
  19. SQL> analyze index test_idx1 validate structure;  
  20.   
  21. Index analyzed.  
  22. SQL> r  
  23.   1  select height,  
  24.   2         lf_rows,  
  25.   3         lf_blks,  
  26.   4         del_lf_rows,  
  27.   5         btree_space,  
  28.   6         used_space,  
  29.   7         pct_used,  
  30.   8         ((used_space - del_lf_rows_len) / btree_space) pct_unused,  
  31.   9         ((lf_rows - del_lf_rows) / lf_rows) pct_undel_rows  
  32.  10    from index_stats  
  33.  11   where name = 'TEST_IDX1'  
  34.  12*  
  35.   
  36.     HEIGHT    LF_ROWS    LF_BLKS DEL_LF_ROWS BTREE_SPACE USED_SPACE   PCT_USED PCT_UNUSED PCT_UNDEL_ROWS  
  37. ---------- ---------- ---------- ----------- ----------- ---------- ---------- ---------- --------------  
  38.          2      10000         21           0      175944     150021         86 .852663347              1  
  39.   
  40. SQL>   
  41. SQL> analyze index test_idx1 validate structure;  
  42.   
  43. Index analyzed.  
  44.   
  45. SQL> select height,  
  46.   2         lf_rows,  
  47.   3         lf_blks,  
  48.   4         del_lf_rows,  
  49.   5         btree_space,  
  50.   6         used_space,  
  51.   7         pct_used,  
  52.   8         ((used_space - del_lf_rows_len) / btree_space) pct_unused,  
  53.   9         ((lf_rows - del_lf_rows) / lf_rows) pct_undel_rows  
  54.  10    from index_stats  
  55.  11   where name = 'TEST_IDX1';  
  56.   
  57.     HEIGHT    LF_ROWS    LF_BLKS DEL_LF_ROWS BTREE_SPACE USED_SPACE   PCT_USED PCT_UNUSED PCT_UNDEL_ROWS  
  58. ---------- ---------- ---------- ----------- ----------- ---------- ---------- ---------- --------------  
  59.          2      10000         21        9999      175944     150021         86 .001329969          .0001  
  60.   
  61. SQL>   
  62. SQL> alter index test_idx1 deallocate unused;  
  63.   
  64. Index altered.  
  65.   
  66. SQL> analyze index test_idx1 validate structure;  
  67.   
  68. Index analyzed.  
  69. SQL> select height,  
  70.   2         lf_rows,  
  71.   3         lf_blks,  
  72.   4         del_lf_rows,  
  73.   5         btree_space,  
  74.   6         used_space,  
  75.   7         pct_used,  
  76.   8         ((used_space - del_lf_rows_len) / btree_space) pct_unused,  
  77.   9         ((lf_rows - del_lf_rows) / lf_rows) pct_undel_rows  
  78.  10    from index_stats  
  79.  11   where name = 'TEST_IDX1';  
  80.   
  81.     HEIGHT    LF_ROWS    LF_BLKS DEL_LF_ROWS BTREE_SPACE USED_SPACE   PCT_USED PCT_UNUSED PCT_UNDEL_ROWS  
  82. ---------- ---------- ---------- ----------- ----------- ---------- ---------- ---------- --------------  
  83.          2      10000         21        9999      175944     150021         86 .001329969          .0001  
  84.   
  85. SQL>   


收集統(tǒng)計信息,之后可以看到在dba_indexes中依然顯示存在的索引葉塊,優(yōu)化器從而使用該索引。

[sql] view plain copy
  1. SQL> exec dbms_stats.gather_table_stats('SYS','TEST',cascade=>true);  
  2.   
  3. PL/SQL procedure successfully completed.  
  4.   
  5. SQL>  select index_name,leaf_blocks,num_rows,degree from dba_indexes where index_name='TEST_IDX1';  
  6.   
  7. INDEX_NAME                     LEAF_BLOCKS   NUM_ROWS DEGREE  
  8. ------------------------------ ----------- ---------- ----------------------------------------  
  9. TEST_IDX1                                1          1 1  
  10.   
  11. SQL> set autotrace trace exp  
  12. sSQL>     
  13. SQL> select * from test where id<20;  
  14.   
  15. Execution Plan  
  16. ----------------------------------------------------------  
  17. Plan hash value: 2624864549  
  18.   
  19. -----------------------------------------------------------------------------------------  
  20. | Id  | Operation                   | Name      | Rows  | Bytes | Cost (%CPU)| Time     |  
  21. -----------------------------------------------------------------------------------------  
  22. |   0 | SELECT STATEMENT            |           |     1 |     7 |     3   (0)| 00:00:01 |  
  23. |   1 |  TABLE ACCESS BY INDEX ROWID| TEST      |     1 |     7 |     3   (0)| 00:00:01 |  
  24. |*  2 |   INDEX RANGE SCAN          | TEST_IDX1 |     1 |       |     2   (0)| 00:00:01 |  
  25. -----------------------------------------------------------------------------------------  
  26.   
  27. Predicate Information (identified by operation id):  
  28. ---------------------------------------------------  
  29.   
  30.    2 - access("ID"<20)  
  31.   
  32. SQL>   


但是注意:使用analyze index index_name validate structure ;進行索引分析的時候會鎖定相應的對象直到該命令執(zhí)行完成,如果不加鎖可以使用online參數(shù),但使用online參數(shù)數(shù)據(jù)信息又不會記錄到index_stats視圖,且在重建索引的過程中會產(chǎn)生很多的redo日志,可以考慮使用nologging參數(shù),另外當在分析完成后在執(zhí)行插入操作,那么相應的del_lf_rows將會改變從而影響對索引的分析信息提取:
eg:

[sql] view plain copy
  1. SQL> select * from test;           
  2.   
  3.         ID TEX  
  4. ---------- ---  
  5.      10000 Amy  
  6.   
  7. SQL> insert into test values(10001,'Rhys');  
  8. insert into test values(10001,'Rhys')  
  9.                               *  
  10. ERROR at line 1:  
  11. ORA-12899: value too large for column "SYS"."TEST"."TEXT" (actual: 4, maximum: 3)  
  12.   
  13.   
  14. SQL> desc test               
  15.  Name                                                                                                              Null?    Type  
  16.  ----------------------------------------------------------------------------------------------------------------- -------- ----------------------------------------------------------------------------  
  17.  ID                                                                                                                         NUMBER  
  18.  TEXT                                                                                                                       CHAR(3)  
  19.   
  20. SQL> alter table test modify text char(15);  
  21.   
  22. Table altered.  
  23.   
  24. SQL> insert into test values(10001,'Rhys');  
  25.   
  26. 1 row created.  
  27.   
  28. SQL> commit;  
  29.   
  30. Commit complete.  
  31.   
  32. SQL> select height,  
  33.   2         lf_rows,  
  34.   3         lf_blks,  
  35.   4         del_lf_rows,  
  36.   5         btree_space,  
  37.   6         used_space,  
  38.        pct_used,  
  39.   7    8         ((used_space - del_lf_rows_len) / btree_space) pct_unused,  
  40.   9         ((lf_rows - del_lf_rows) / lf_rows) pct_undel_rows  
  41.  10    from index_stats  
  42.  11   where name = 'TEST_IDX1';  
  43.   
  44.     HEIGHT    LF_ROWS    LF_BLKS DEL_LF_ROWS BTREE_SPACE USED_SPACE   PCT_USED PCT_UNUSED PCT_UNDEL_ROWS  
  45. ---------- ---------- ---------- ----------- ----------- ---------- ---------- ---------- --------------  
  46.          2      10000         21        9999      175944     150021         86 .001329969          .0001  
  47.   
  48. SQL> analyze index test_idx1 validate structure;  
  49.   
  50. Index analyzed.  
  51.   
  52. SQL> select height,  
  53.   2         lf_rows,  
  54.   3         lf_blks,  
  55.        del_lf_rows,  
  56.   4    5         btree_space,  
  57.   6         used_space,  
  58.        pct_used,  
  59.   7    8         ((used_space - del_lf_rows_len) / btree_space) pct_unused,  
  60.   9         ((lf_rows - del_lf_rows) / lf_rows) pct_undel_rows  
  61.  10    from index_stats  
  62.  where name = 'TEST_IDX1';  
  63.  11    
  64.     HEIGHT    LF_ROWS    LF_BLKS DEL_LF_ROWS BTREE_SPACE USED_SPACE   PCT_USED PCT_UNUSED PCT_UNDEL_ROWS  
  65. ---------- ---------- ---------- ----------- ----------- ---------- ---------- ---------- --------------  
  66.          2       9584         21        9582      175944     143786         82 .001420907     .000208681  
  67.   
  68. SQL>   


從以上可以看出兩點內(nèi)容,產(chǎn)生索引數(shù)據(jù)之后剩余的空間不會返還給數(shù)據(jù)庫,但是當插入新數(shù)據(jù)的時候?qū)⒂锌赡苤匦吕弥氨粍h除數(shù)據(jù)的空間,另外一點可以看del_lf_row已經(jīng)評估出現(xiàn)錯誤,到目前為止剛剛開始刪除9999條數(shù)據(jù),然后插入一條數(shù)據(jù)在進行分析,那么現(xiàn)在既然是9582,因此不能僅僅依靠del_lf_rows進行索引重建評估。以前記得有個朋友曾經(jīng)提過這么一個問題,說是測試環(huán)境庫執(zhí)行一條sql會非常的塊,但是導到正式環(huán)境卻很慢,但是執(zhí)行計劃都是一樣的,我的懷疑就是需要重建正式環(huán)境庫的索引。因此,如果確定對 索引相同部分執(zhí)行了大量刪除操作,產(chǎn)生了大量的索引碎片,并且查詢每次讀取了大量的索引行,索引被頻繁使用,這時候重建索引是有價值的。
第二種:合并索引
  合并索引就是將索引段中相鄰的索引塊其中空閑空間進行整合重組,從而釋放索引塊空間,這比較類似于我們windows的磁盤碎片整理,但是注意該過程不會將騰出的空間返回與數(shù)據(jù)庫,而是加入到空閑空間列表中,以便下次在進行使用。這種操作對于那種以序列或是時間日志為字段的表是有非常重要價值的,因為當我們對這些表刪除了大部分數(shù)據(jù),那么其中很多空間是無法在進行使用的,那么在我們制定謂詞查詢的時候通常會掃描索引中很多空快,那么合并索引就將空的索引塊進行釋放與索引塊的空閑列表中。
語句非常簡單:
alter index index_name coalesce;
合并索引與重建索引不同事,合并索引不會降低索引的高度,而是對其數(shù)據(jù)條目進行重組整合,但是重建可能會降低索引高度,另外重建索引需要2倍的磁盤空間,首先需要存儲原先的索引條目數(shù)據(jù),還需要額外的空間存儲新調(diào)整 的索引數(shù)據(jù)直到重建完成才可。

注:合并索引是一種在線操作。
第三種:shrink 索引:
 因為shrink是一個耗資源相對嚴重的過程,因此兩個過程,一個是compact參數(shù),另一個是直接shrink space,第一種類似于coalesce但是相比會產(chǎn)生更多的redo日志,執(zhí)行完后不會釋放空間,但是shrink space 除了整理碎片還可以將空間釋放給表空間,但是shrink space雖然是在線可以做的,依然會產(chǎn)生過打的redo日志。除此之外shrink space還要啟動行移動。
eg:
alter index index_name shrink space compact;
alter index index_name shrink space;
注:Shrink operations can be performed only on segments in locally managed tablespaces with automatic segment space management (ASSM).



select name,
         blocks,
         del_lf_rows_len,
         lf_rows_len,
         (del_lf_rows_len / lf_rows_len) * 100,
         (DEL_LF_ROWS / LF_ROWS) * 100
    from index_stats;
  
  NAME          BLOCKS     DEL_LF_ROWS_LEN      LF_ROWS_LEN      (DEL_LF_ROWS_LEN / LF_ROWS_LEN) * 100          (DEL_LF_ROWS / LF_ROWS) * 100
  ------------  ---------  -------------------  ---------------  ----------- ---------------------------------   -------------------------
  IND_OBJ_ID    384        766085               1906952          40.1732713                                      40.2394062
  
  索引碎片比率:(del_lf_rows_len / lf_rows_len) * 100,如果百分比超過20%就說明索引碎片比率很高了。需要整理碎片。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI