Java,J2EE,Weblogic,Oracle

          java項目隨筆
          隨筆 - 90, 文章 - 6, 評論 - 61, 引用 - 0
          數據加載中……

          Oracle數據庫中索引的維護

           

          本文只討論Oracle中最常見的索引,即是B-tree索引。本文中涉及的數據庫版本是
           一. 查看系統表中的用戶索引
           在Oracle中,SYSTEM表是安裝數據庫時自動建立的,它包含數據庫的全部數據字典,
           一般來說,應該盡量避免在SYSTEM表中存儲非SYSTEM用戶的對象。因為這樣會帶來數
          據庫維護和管理的很多問題。一旦SYSTEM表損壞了,只能重新生成數據庫。我們可以用下面的
            select count(*)
            from dba_indexes
            where tablespace_name = 'SYSTEM'
            and owner not in ('SYS','SYSTEM')
            /
           二. 索引的存儲情況檢查
           Oracle為數據庫中的所有數據分配邏輯結構空間。數據庫空間的單位是數據塊(
          block)、范圍(extent)和段(segment)。
           Oracle數據塊(block)是Oracle使用和分配的最小存儲單位。它是由數據庫建立時
          設置的DB_BLOCK_SIZE決定的。一旦數據庫生成了,數據塊的大小不能改變。要想改變只能重
          新建立數據庫。(在Oracle9i中有一些不同,不過這不在本文討論的范圍內。)
           Extent是由一組連續的block組成的。一個或多個extent組成一個segment。當一個
          segment中的所有空間被用完時,Oracle為它分配一個新的extent。

           Segment是由一個或多個extent組成的。它包含某表空間中特定邏輯存儲結構的所有
          數據。一個段中的extent可以是不連續的,甚至可以在不同的數據文件中。
           一個object只能對應于一個邏輯存儲的segment,我們通過查看該segment中的
           (1)查看索引段中extent的數量:
            select segment_name, count(*)
            from dba_extents
            where segment_type='INDEX'
            and owner=UPPER('&owner')
            group by segment_name
            /
           (2)查看表空間內的索引的擴展情況:
            select
            substr(segment_name,1,20) "SEGMENT NAME",

            bytes,
            count(bytes)
            from dba_extents
            where segment_name in
            ( select index_name
            from dba_indexes
            where tablespace_name=UPPER('&表空間'))
            group by segment_name,bytes
            order by segment_name
            /
            三. 索引的選擇性
           索引的選擇性是指索引列中不同值的數目與表中記錄數的比。如果一個表中有2000條
          記錄,表索引列有1980個不同的值,那么這個索引的選擇性就是1980/2000=0.99。
           一個索引的選擇性越接近于1,這個索引的效率就越高。
           如果是使用基于cost的最優化,優化器不應該使用選擇性不好的索引。如果是使用基
          于rule的最優化,優化器在確定執行路徑時不會考慮索引的選擇性(除非是唯一性索引),并
          且不得不手工優化查詢以避免使用非選擇性的索引。
           確定索引的選擇性,可以有兩種方法:手工測量和自動測量。
           (1)手工測量索引的選擇性
           如果要根據一個表的兩列創建兩列并置索引,可以用以下方法測量索引的選擇性:
           列的選擇性=不同值的數目/行的總數
            select count(distinct 第一列||'%'||第二列)/count(*)
            from 表名
            /
           如果我們知道其中一列索引的選擇性(例如其中一列是主鍵),那么我們就可以知道
           手工方法的優點是在創建索引前就能評估索引的選擇性。
           (2)自動測量索引的選擇性
           如果分析一個表,也會自動分析所有表的索引。
           第一,為了確定一個表的確定性,就要分析表。
            analyze table 表名
            compute statistics
            /
           第二,確定索引里不同關鍵字的數目:
            select distinct_keys
            from user_indexes
            where table_name='表名'
            and index_name='索引名'
            /
           第三,確定表中行的總數:
            select num_rows
            from user_tables
            where table_name='表名'
            /
           第四,索引的選擇性=索引里不同關鍵字的數目/表中行的總數:
            select i.distinct_keys/t.num_rows
            from
            user_indexes i,
            user_tables t
            where i.table_name='表名'
            and i.index_name='索引名'
            and i.table_name=t.table_name
            /
           第五,可以查詢USER_TAB_COLUMNS以了解每個列的選擇性。
           表中所有行在該列的不同值的數目:
            select
            column_name,
            num_distinct
            from user_tab_columns
            where table_name='表名'
            /
           列的選擇性=NUM_DISTINCT/表中所有行的總數,查詢USER_TAB_COLUMNS有助測量每個
          列的選擇性,但它并不能精確地測量列的并置組合的選擇性。要想測量一組列的選擇性,需要
           四. 確定索引的實際碎片
           隨著數據庫的使用,不可避免地對基本表進行插入,更新和刪除,這樣導致葉子行在
          索引中被刪除,使該索引產生碎片。插入刪除越頻繁的表,索引碎片的程度也越高。碎片的產
          生使訪問和使用該索引的I/O成本增加。碎片較高的索引必須重建以保持最佳性能。
           (1)利用驗證索引命令對索引進行驗證。
           這將有價值的索引信息填入index_stats表。
            validate index 用戶名.索引名
            /
           (2)查詢index_stats表以確定索引中刪除的、未填滿的葉子行的百分比。
            select
            name,
            del_lf_rows,
            lf_rows,
            round((del_lf_rows/(lf_rows+0.0000000001))*100) "Frag Percent"
            from index_stats
            /
           (3)如果索引的葉子行的碎片超過10%,考慮對索引進行重建。
            alter index 用戶名.索引名 rebuild
            tablespace 表空間名
            storage(initial 初始值 next 擴展值)
            nologging
            /
           (4)如果出于空間或其他考慮,不能重建索引,可以整理索引。
            alter index用戶名.索引名 coalesce
            /
           (5)清除分析信息
            analyze index 用戶名.索引名
            delete statistics
            /
            五. 重建索引
           (1)檢查需要重建的索引。
           根據以下幾方面進行檢查,確定需要重建的索引。
           第一,查看SYSTEM表空間中的用戶索引。
           為了避免數據字典的碎片出現,要盡量避免在SYSTEM表空間出現用戶的表和索引。
            select index_name
            from dba_indexes
            where tablespace_name='SYSTEM'
            and owner not in ('SYS','SYSTEM')
            /
           第二,確保用戶的表和索引不在同一表空間內。
           表和索引對象的第一個規則是把表和索引分離。把表和相應的索引建立在不同的表空
          間中,最好在不同的磁盤上。這樣可以避免在數據管理和查詢時出現的許多I/O沖突。
            set linesize 120
            col "OWNER" format a20
            col "INDEX" format a30
            col "TABLE" format a30
            col "TABLESPACE" format a30
            select
            i.owner "OWNER",
            i.index_name "INDEX",
            t.table_name "TABLE",
            i.tablespace_name "TABLESPACE"
            from
            dba_indexes i,
            dba_tables t
            where i.owner=t.owner
            and i.table_name=t.table_name
            and i.tablespace_name=t.tablespace_name
            and i.owner not in ('SYS','SYSTEM')
            /
           第三,查看數據表空間里有哪些索引
           用戶的默認表空間應該不是SYSTEM表空間,而是數據表空間。在建立索引時,如果不
          指定相應的索引表空間名,那么,該索引就會建立在數據表空間中。這是程序員經常忽略的一
          個問題。應該在建索引時,明確的指明相應的索引表空間。
            col segment_name format a30
            select
            owner,
            segment_name,
            sum(bytes)
            from dba_segments
            where tablespace_name='數據表空間名'
            and segment_type='INDEX'
            group by owner,segment_name
            /
           第四,查看哪個索引被擴展了超過10次
           隨著表記錄的增加,相應的索引也要增加。如果一個索引的next extent值設置不合
          理(太小),索引段的擴展變得很頻繁。索引的extent太多,檢索時的速度和效率就會降低。
            set linesize 100
            col owner format a10
            col segment_name format a30
            col tablespace_name format a30
            select
            count(*),
            owner,
            segment_name,
            tablespace_name
            from dba_extents
            where segment_type='INDEX'
            and owner not in ('SYS','SYSTEM')
            group by owner,segment_name,tablespace_name

            order by count(*) desc
            /
            
           (2)找出需要重建的索引后,需要確定索引的大小,以設置合理的索引存儲參數。
            set linesize 120
            col "INDEX" format a30
            col "TABLESPACE" format a20
            select
            owner "OWNER",
            segment_name "INDEX",
            tablespace_name "TABLESPACE",
            bytes "BYTES/COUNT",
            sum(bytes) "TOTAL BYTES",
            round(sum(bytes)/(1024*1024),0) "TOTAL M",
            count(bytes) "TOTAL COUNT"
            from dba_extents
            where segment_type='INDEX'
            and segment_name in
            (
            '索引名1',
            '索引名2',
            ......
            )
            group by owner,segment_name,segment_type,tablespace_name,bytes
            order by owner,segment_name
            /
           (3)確定索引表空間還有足夠的剩余空間。
           確定要把索引重建到哪個索引表空間中。要保證相應的索引表空間有足夠的剩余空間
            select round(bytes/(1024*1024),2) free(M)
            from sm$ts_free
            where tablespace_name='表空間名'
            /
           (4)重建索引。
           重建索引時要注意以下幾點:
           a.如果不指定tablespace名,索引將建在用戶的默認表空間。
           b.如果不指定nologging,將會寫日志,導致速度變慢。由于索引的重建沒有恢復的
           c.如果出現資源忙,表明有進程正在使用該索引,等待一會再提交。
            alter index 索引名
            rebuild
            tablespace 索引表空間名
            storage(initial 初始值 next 擴展值)
            nologging
            /
           (5)檢查索引。
           對重建好的索引進行檢查。
            select *
            from dba_extents
            where segment_name='索引名'
            /
           (6)根據索引進行查詢,檢查索引是否有效
           使用相應的where條件進行查詢,確保使用該索引。看看使用索引后的效果如何。
            select *
            from dba_ind_columns
            where index_name like '表名%'
            /
           然后,根據相應的索引項進行查詢。
            select *
            from '表名%'
            where ......
            /
           (6)找出有碎片的表空間,并收集其碎片。
           重建索引后,原有的索引被刪除,這樣會造成表空間的碎片。
            select 'alter tablespace '||tablespace_name||' coalesce;'
            from dba_free_space_coalesced
            where percent_blocks_coalesced!=100
            /
           整理表空間的碎片。
            alter tablespace 表空間名 coalesce
            /

          posted on 2010-08-19 10:42 龔椿深 閱讀(323) 評論(0)  編輯  收藏


          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 娱乐| 来宾市| 昭通市| 视频| 红桥区| 江津市| 胶州市| 台北县| 循化| 吴堡县| 佛学| 鄂尔多斯市| 楚雄市| 增城市| 扶绥县| 江永县| 泰宁县| 扬中市| 库车县| 白朗县| 余干县| 阳泉市| 舟曲县| 平潭县| 和政县| 黎川县| 水城县| 晋江市| 宁强县| 辽源市| 安西县| 井陉县| 徐闻县| 金沙县| 青河县| 灵寿县| 财经| 乌苏市| 阿尔山市| 枝江市| 淮滨县|