zoukankan      html  css  js  c++  java
  • Oracle索引碎片检查及定期重建常用表的索引

    背景说明:

           今天查阅书籍时,偶然间发现“在对某个索引行执行删除操作时,只是为该行增加了一个删除标记,这个索引行并不会释放它的存储空间,Insert产生的新的索引行也不能被插入到该位置。索引列的修改过程其实是将对应的列值删除,然后再插入新的列值(与数据行本身的修改是不一致的,这也正是我们尽量不使用修改频繁的列来创建索引的原因)。所以,无论是插入、修改、删除,都需要消耗存储空间,增大B-Tree索引结构的深度,影响数据的查询速度。尤其是删除和修改,不仅造成了存储空间的浪费,而且增加了扫描索引块的数量”,这就是所谓的索引碎片问题,建议定期对经常使用的表执行检查和重建索引操作。

    问题重现:

          经测试,收集统计信息等操作,无法释放索引删除块所占用的存储空间。

    analyze table tkk29 compute statistics;

    select t.index_name, t.distinct_keys, t.num_rows, t.sample_size, t.last_analyzed
          , t.blevel, t.leaf_blocks, t.*
    from user_indexes t
    where t.table_name = upper('tkk29');

    tkk2901

    delete from tkk29
    where mod(trunc((sysdate-createddate) * 24 * 60), 2) = 0;

    analyze table tkk29 compute statistics;

    analyze index IDX_tkk29_PARTICIPANT validate structure;

    select t.name, t.blocks, t.lf_rows, t.del_lf_rows, t.lf_rows - t.del_lf_rows as lf_rows_used
           , to_char((t.del_lf_rows/t.lf_rows) * 100, '999.999') as ratio, t.*
    from index_stats t

    image

    image

    alter index IDX_tkk29_PARTICIPANT rebuild;

    alter index IDX_tkk29_ACTUALPARTICIPANT rebuild;

    analyze index IDX_tkk29_PARTICIPANT validate structure;

    image

    image

    重建索引:

    CREATE OR REPLACE TYPE strsplit_type AS TABLE OF VARCHAR2(32676);
    
    CREATE OR REPLACE FUNCTION strsplit(p_value VARCHAR2, p_split VARCHAR2 := ',')
     --usage: select * from table(strsplit('1,2,3,4,5'))
     RETURN strsplit_type
    PIPELINED IS
     v_idx       INTEGER;
     v_str       VARCHAR2(500);
     v_strs_last VARCHAR2(4000) := p_value;
    BEGIN
     LOOP
      v_idx := instr(v_strs_last, p_split);
      EXIT WHEN v_idx = 0;
      v_str       := substr(v_strs_last, 1, v_idx - 1);
      v_strs_last := substr(v_strs_last, v_idx + 1);
      PIPE ROW(v_str);
     END LOOP;
     PIPE ROW(v_strs_last);
     RETURN;
    END strsplit;
    CREATE OR REPLACE PROCEDURE UP_CHECK_TO_REBUILD_INDEX
    (
           tbNames varchar
    )
    IS
        sqlstr VARCHAR2(100);
        idx_ratio INT;
    BEGIN       
        --DECLARE sqlstr VARCHAR2(100);
        --        idx_ratio INT;
        BEGIN
            FOR idx IN (SELECT t.index_name FROM user_indexes t 
                        WHERE t.index_type = 'NORMAL' AND t.status = 'VALID' AND t.temporary = 'N' AND t.leaf_blocks > 100
                            AND t.table_name IN (SELECT UPPER(TRIM(COLUMN_VALUE)) from table(strsplit(tbNames))) --//('TKK29')
                        ORDER BY t.table_name, t.index_name
                       )
            LOOP
                DBMS_OUTPUT.put_LINE(idx.index_name || ' ANALYZE START ' || TO_CHAR(SYSDATE, 'yyyy-MM-dd hh24:mi:ss'));
                sqlstr := 'ANALYZE INDEX ' || idx.Index_Name || ' VALIDATE STRUCTURE';
                EXECUTE IMMEDIATE sqlstr;
                
                SELECT TRUNC((t.del_lf_rows/t.lf_rows) * 100) INTO idx_ratio 
                FROM index_stats t WHERE t.name=idx.index_name AND ROWNUM=1;
                
                IF (idx_ratio >= 15) THEN
                   DBMS_OUTPUT.put_line('    REINDEX ' || TO_CHAR(SYSDATE, 'yyyy-MM-dd hh24:mi:ss') || ' ratio: ' || idx_ratio);
                   sqlstr := 'ALTER INDEX ' || idx.index_name || ' REBUILD';
                   EXECUTE IMMEDIATE sqlstr;
                END IF;
            END LOOP;
        END;
    END UP_CHECK_TO_REBUILD_INDEX;
    
    
    
    SQL>exec UP_CHECK_TO_REBUILD_INDEX('TKK29, muser');
    
    begin
           UP_CHECK_TO_REBUILD_INDEX('TKK29, muser');
    end;

    PK_MUSER ANALYZE START 2016-01-29 17:49:19
    IDX_TKK29_ACTIVITYINSTANCEID ANALYZE START 2016-01-29 17:49:19
        REBUILD INDEX START 2016-01-29 17:49:20 ratio: 50
    IDX_TKK29_ACTUALPARTICIPANT ANALYZE START 2016-01-29 17:49:22
    IDX_TKK29_COMPLETEDDATE ANALYZE START 2016-01-29 17:49:22
        REBUILD INDEX START 2016-01-29 17:49:22 ratio: 36
    IDX_TKK29_PARTICIPANT ANALYZE START 2016-01-29 17:49:23
    IDX_TKK29_PROCESSINSTANCEID ANALYZE START 2016-01-29 17:49:23
        REBUILD INDEX START 2016-01-29 17:49:24 ratio: 50
    IDX_TKK29_STATEDDATE ANALYZE START 2016-01-29 17:49:25
        REBUILD INDEX START 2016-01-29 17:49:25 ratio: 33
    PK_TKK29 ANALYZE START 2016-01-29 17:49:27
        REBUILD INDEX START 2016-01-29 17:49:27 ratio: 50

    备注:

        真实场景请考虑索引列的修改、数据删除的概率,结合表的数据量大小等多种因素制定合理的维护计划;另外,分区表的不同分区应该有不同的策略。

  • 相关阅读:
    SPOJ SAMER08A
    SPOJ TRAFFICN
    CS Academy Set Subtraction
    CS Academy Bad Triplet
    CF Round 432 C. Five Dimensional Points
    CF Round 432 B. Arpa and an exam about geometry
    SPOJ INVCNT
    CS Academy Palindromic Tree
    身体训练
    简单瞎搞题
  • 原文地址:https://www.cnblogs.com/zhaoguan_wang/p/5169821.html
Copyright © 2011-2022 走看看