zoukankan      html  css  js  c++  java
  • 索引rebuild与rebuild online区别

    索引rebuild与rebuild online区别

    1.0目的,本篇文档探讨索引rebuild 与 rebuild online的区别

    2.0猜测:已有的知识
    2.1对索引rebuild重建会对表申请TM4级表锁,将会影响业务修改数据,而对索引进行rebuild online则不影响业务修改数据,但是可能会失败。
    2.2对索引rebuild online,对于一个大的分区表,rebuild online速度非常慢,而rebuild速度对比很快
    2.3对索引rebuild online查询数据库V$lOCK视图,发现对多个对象存在TM2、某个对象TM4级锁,但是不知道是什么对象

    3.0实验思路
    1.从锁角度查询区别
    2.从执行计划查询区别
    3.从10046分析查询区别(没整明白,可忽略)
    申明,本次操作版本11.2.0.4

    4.0测试看锁
    创建一个分区表Local 索引,rebuild :rebuild online对比分析,得出结论
    4.1 创建测试对象
    SCOTT > create table t(id int,name varchar2(20)) partition by hash(id) partitions 4;
    set timing on
    declare
    v_id int;
    begin
    for v_id in 1 .. 500000
    loop
    insert into t values(v_id,'test'||v_id);
    end loop;
    commit;
    end;
    /
    Elapsed: 00:01:36.68
    #drop index t_ind;
    create index t_p_ind on t(id) local;

    SCOTT > select a.TABLE_NAME,a.PARTITION_NAME,bytes/1024/1024 from user_tab_partitions a,dba_segments b where a.partition_name=b.PARTITION_NAME and a.table_name='T';
    TABLE_NAME PARTITION_NAME BYTES/1024/1024
    ------------------ ------------------- ---------------
    T SYS_P112 8
    T SYS_P111 8
    T SYS_P110 8
    T SYS_P109 8
    --查询重建索引SQL
    SELECT 'alter INDEX SCOTT.'
    || index_name
    || ' REBUILD PARTITION '
    || PARTITION_NAME||';'
    FROM DBA_IND_PARTITIONS
    where INDEX_OWNER='SCOTT' AND INDEX_NAME='T_P_IND';
    'ALTERINDEXSCOTT.'||INDEX_NAME||'REBUILDPARTITION'||PARTITION_NAME||';'
    ----------------------------------------------------------------------
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P113;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P114;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P115;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P116;

    test1
    #drop table test1 purge;
    create table t1 as select * from t;
    SCOTT > select a.TABLE_NAME,segment_name,bytes/1024/1024 from user_tables a,dba_segments b where a.TABLE_NAME=b.segment_name and a.table_name='T1' and owner='SCOTT';
    TABLE_NAME SEGMENT_NAME BYTES/1024/1024
    ------------------------------ -------------------------- ---------------
    T1 T1 12

    create index t_ind on t1(id);


    4.2 分区表,rebuild看锁

    --会话一、delete操作
    SCOTT > delete t where id=1;
    1 row deleted.
    --会话二、rebuild
    HR > alter session set ddl_lock_timeout=60000;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P113;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P114;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P115;
    --执行上述三个分区索引rebuild都不存在问题,可以rebuild OK
    HR > alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P116;


    --会话hang住

    --select v$lOCK

    select * from
    (select s.sid,l.type,id1,lmode,request,username,event,sql_id from v$lock l,v$session s where l.sid=s.sid and l.type in('TX','TM')) a left join
    (select owner,object_name,object_type,object_id from dba_objects)b on a.id1=b.object_id order by 1;
    SID TY ID1 LMODE REQUEST USERNAME EVENT SQL_ID OWNER OBJECT OBJECT_TYPE OBJECT_ID
    ----- -- ------ ----- ------- -------- ---------------------------- ------------- -------- ------- ----------------------------
    58 TM 91888 2 0 HR enq: TM - contention 02ywzvmsk9ng4 SCOTT T TABLE 91888
    58 TM 91892 0 4 HR enq: TM - contention 02ywzvmsk9ng4 SCOTT T TABLE PARTITION 91892
    64 TX 131087 6 0 SCOTT SQL*Net message from client
    64 TM 91892 3 0 SCOTT SQL*Net message from client SCOTT T TABLE PARTITION 91892
    64 TM 91888 3 0 SCOTT SQL*Net message from client SCOTT T TABLE 91888
    6 rows selected.
    rebuild local index申请表分区TM4号锁,申请表TM2号锁
    --查询申请分区的记录
    SYS@ENMO>select OWNER,OBJECT_NAME,SUBOBJECT_NAME,OBJECT_ID,OBJECT_TYPE from dba_objects where owner='SCOTT' and object_name='T';

    OWNER OBJECT_NAME SUBOBJECT_NAME OBJECT_ID OBJECT_TYPE
    -------- -------------- -------------------- ---------- -------------------
    SCOTT T 91888 TABLE
    SCOTT T SYS_P109 91889 TABLE PARTITION
    SCOTT T SYS_P110 91890 TABLE PARTITION
    SCOTT T SYS_P111 91891 TABLE PARTITION
    SCOTT T SYS_P112 91892 TABLE PARTITION --


    --会话三、delete操作
    SYS>delete scott.t where id=300000;--hang住

    --dml操作被rebuild会话锁住
    SYS > select INST_ID II,sid,serial#,username,schemaname,sql_id,machine,program,EVENT,BLOCKING_INSTANCE BI,BLOCKING_SESSION BS from gv$session where blocking_session is not null order by BLOCKING_SESSION;
    II SID SERIAL# USERNAME SCHEMANAME SQL_ID MACHINE PROGRAM EVENT BI BS
    -- -------------- --------- ----------- ------------- --------- ------------------------- -------------------- --- ------
    1 41 2469 SYS SYS g4022z4dskb8s enmo sqlplus@enmo (TNS V1-V3) enq: TM - contention 1 58
    1 58 593 HR HR 02ywzvmsk9ng4 enmo sqlplus@enmo (TNS V1-V3) enq: TM - contention 1 64

    --因此,直接对索引进行rebuild,重建过程中导致业务无法对分区表的该分区字段进行dml操作[

    --疑问? 为何会话3,执行delete操作会Hang住,因为该数据存储在索引rebuild分区上,索引申请该分区TM4号锁,堵塞了dml申请TM3号锁,如果确定?
    查询BLOCL_ID
    select id,rowid,
    dbms_rowid.rowid_object(rowid) object#,
    dbms_rowid.rowid_relative_fno(rowid) file#,
    dbms_rowid.rowid_block_number(rowid) block#,
    dbms_rowid.rowid_row_number(rowid) row# from scott.t where id in(1,300000);
    ID ROWID OBJECT# FILE# BLOCK# ROW#
    ---------- ------------------ ---------- ---------- ---------- ----------
    1 AAAWb0AAEAACvPCAAp 91892 4 717762 41
    300000 AAAWb0AAEAACvN8AAw 91892 4 717692 48

    select
    t.segment_name,
    t.partition_name,
    t.BLOCK_ID,(t.BLOCKS + t.BLOCK_ID -1) "MAX_BLOCK_ID"
    from sys.dba_extents t,dba_tab_partitions p
    where t.PARTITION_NAME=p.partition_name and p.TABLE_OWNER='SCOTT' and p.table_name='T';
    SEGMENT_NA PARTITION_NAME BLOCK_ID MAX_BLOCK_ID
    ---------- ------------------------------ ---------- ------------
    T SYS_P109 714368 715391
    T SYS_P110 715392 716415
    T SYS_P111 716416 717439
    T SYS_P112 717440 718463 --717692--717762
    --无法通过视图中查询索引记录的rowid信息,可以通过索引申请object_id,通过被阻塞的rowid找到对应Block_id与之对应的partition name



    4.3 分区表,rebuild online看锁

    --会话一、delete操作
    SCOTT > delete t where id=1;
    1 row deleted.
    --会话二、rebuild
    SYS > alter session set ddl_lock_timeout=60000;
    SYS > alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P116 online;

    --会话hang住

    --select v$lOCK

    select * from
    (select s.sid,l.type,id1,lmode,request,username,event,sql_id from v$lock l,v$session s where l.sid=s.sid and l.type in('TX','TM')) a left join
    (select owner,object_name,object_type,object_id from dba_objects)b on a.id1=b.object_id order by 1;

    SID TY ID1 LMODE REQUEST USERNAME EVENT SQL_ID OWNER OBJECT_NAME OBJECT_TYPE OBJECT_ID
    ---- -- ---------- ----- ------- -------- ------------------------------ ------------- -------- -------------- --------------------------
    41 TM 91888 2 0 SYS enq: TX - row lock contention 821crb119wpc6 SCOTT T TABLE 91888
    41 TX 131074 0 4 SYS enq: TX - row lock contention 821crb119wpc6
    41 TM 91926 4 0 SYS enq: TX - row lock contention 821crb119wpc6 SCOTT SYS_JOURNAL_91897 TABLE 91926
    41 TM 91892 2 0 SYS enq: TX - row lock contention 821crb119wpc6 SCOTT T TABLE PARTITION 91892
    41 TX 393227 6 0 SYS enq: TX - row lock contention 821crb119wpc6
    58 TM 91888 3 0 SCOTT SQL*Net message from client SCOTT T TABLE 91888
    58 TX 131074 6 0 SCOTT SQL*Net message from client
    58 TM 91892 3 0 SCOTT SQL*Net message from client SCOTT T TABLE PARTITION 91892

    8 rows selected.


    --rebuild online 查询申请TM锁记录
    SYS@ENMO>select OWNER,OBJECT_NAME,SUBOBJECT_NAME,OBJECT_ID,OBJECT_TYPE from dba_objects where owner='SCOTT' and object_name='T';
    OWNER OBJECT_NAME SUBOBJECT_NAME OBJECT_ID OBJECT_TYPE
    -------- -------------- ------------------------------ ---------- -------------------
    SCOTT T 91888 TABLE --rebuild online申请表TM2级锁
    SCOTT T SYS_P109 91889 TABLE PARTITION
    SCOTT T SYS_P110 91890 TABLE PARTITION
    SCOTT T SYS_P111 91891 TABLE PARTITION
    SCOTT T SYS_P112 91892 TABLE PARTITION --rebuild online申请、分区对象施加TM2号锁

    --疑问?
    rebuild 申请了一个91926 TM 4号锁,SCOTT SYS_JOURNAL_91897 TABLE
    SCOTT > select * from SYS_JOURNAL_91897;
    no rows selected
    SCOTT > desc SYS_JOURNAL_91897
    Name Null? Type
    ------------- -------- ---------------
    C0 NOT NULL NUMBER(38)
    OPCODE CHAR(1)
    PARTNO NUMBER
    RID NOT NULL ROWID


    4.4 测试查询rebuild online期间系统自动创建的测试表记录的信息
    测试对索引rebuild online分区进行delete/update/insert操作,查询临时表记录信息
    --会话三、delete操作
    SYS > delete scott.t where id=300000;
    1 row deleted.
    select * from SYS_JOURNAL_91897

    C0 O PARTNO RID
    ---------- - ---------- ------------------------------
    300000 D 3 D/////AAEAACvN8AAw --允许操作

    --查询分区最大的id值
    select max(id) from t partition(SYS_P112);
    MAX(ID)
    ----------
    499989

    --update 非分区列,发现临时表不记录信息
    update t set NAME='NAME2' where id=499989;

    SCOTT > select * from SYS_JOURNAL_91897;

    C0 O PARTNO RID
    ---------- - ---------- ------------------------------
    300000 D 3 D/////AAEAACvN8AAw
    --update 其它列,并不记录在此视图中

    --update 索引列,发现还需要找到一个值,Update后还存在该表中,暂缓update操作测试
    update t set id=id+400 where id=499989
    *
    ERROR at line 1:
    ORA-14402: updating partition key column would cause a partition change

    --由于insert 随机,因此插入四条记录进行测试
    SCOTT > select * from SYS_JOURNAL_91897;

    C0 O PARTNO RID
    ---------- - ---------- ------------------------------
    300000 D 3 D/////AAEAACvN8AAw
    declare
    v_id int;
    begin
    for v_id in 500001 .. 500004
    loop
    insert into t values(v_id,'test'||v_id);
    end loop;
    commit;
    end;
    /
    SCOTT > select max(id) from t partition(SYS_P112);
    MAX(ID)
    ----------
    500002
    SCOTT > select * from SYS_JOURNAL_91897;

    C0 O PARTNO RID
    ---------- - ---------- ------------------------------
    300000 D 3 D/////AAEAACvN8AAw
    500002 I 3 D/////AAEAACvPiAAA 可以看到Insert操作本行记录

    --对insert记录进行delete,随后修改之前的记录,为insert记录,保证了在一个分区
    delete t where id=500002;
    update t set id=500002 where id=499989;
    --再次查询视图记录
    SCOTT > select * from SYS_JOURNAL_91897;

    C0 O PARTNO RID
    ---------- - ---------- ------------------------------
    300000 D 3 D/////AAEAACvN8AAw
    500002 D 3 D/////AAEAACvPiAAA--之前记录的insert直接转换为delete记录,对一行记录,最后一次变更操作
    499989 D 3 D/////AAEAACvPCAAo
    500002 I 3 D/////AAEAACvPCAAo --非常有意思,这里记录一条update,直接转换为一条delete 一条Insert



    --本次实验可以得到如下结论: 1.rebuild 操作会对分区对象添加TM4号锁,导致该分区对象无法dml操作影响业务
    2.rebuild online则不会影响业务对分区字段dml操作,内部通过临时表记录修改信息,索引重建自动维护(rebuild期间修改的数据)

    5.0 表索引,rebuild看执行计划
    SYS > set autotrace on
    delete scott.t where id=1;
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P116;
    SYS > select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
    --通过种种SQL_ID找执行计划,均失败
    --通过dbms 根据统计信息,模拟执行计划输出!


    5.1 rebuild 分区表、分区索引
    explain plan for
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P116;
    select * from table(dbms_xplan.display);

    Plan hash value: 451004126

    ---------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
    ---------------------------------------------------------------------------------------------------
    | 0 | ALTER INDEX STATEMENT | | 124K| 609K| 102 (1)| 00:00:02 | | |
    | 1 | INDEX BUILD NON UNIQUE | T_P_IND | | | | | | |
    | 2 | SORT CREATE INDEX | | 124K| 609K| | | | |
    | 3 | PARTITION HASH SINGLE| | | | | | 4 | 4 |
    | 4 | INDEX FAST FULL SCAN| T_P_IND | | | | | 4 | 4 |
    ---------------------------------------------------------------------------------------------------
    可以发现,对于分区表,rebuild索引,通过索引范围全扫描,扫描整个分区
    索引快速全扫描->单分区全扫描->创建索引,需要排序->索引创建,非唯一->创建索引语句成功执行


    5.2 rebuild online分区表、分区索引
    explain plan for
    alter INDEX SCOTT.T_P_IND REBUILD PARTITION SYS_P116 online;
    select * from table(dbms_xplan.display);
    ---------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
    ---------------------------------------------------------------------------------------------------
    | 0 | ALTER INDEX STATEMENT | | 124K| 609K| 102 (1)| 00:00:02 | | |
    | 1 | INDEX BUILD NON UNIQUE | T_P_IND | | | | | | |
    | 2 | SORT CREATE INDEX | | 124K| 609K| | | | |
    | 3 | PARTITION HASH SINGLE| | 124K| 609K| 102 (1)| 00:00:02 | 4 | 4 |
    | 4 | TABLE ACCESS FULL | T | 124K| 609K| 102 (1)| 00:00:02 | 4 | 4 |
    ---------------------------------------------------------------------------------------------------
    可以发现,对于分区表,rebuild online索引,进行的是全表扫描,随后分区扫描,
    全表扫描->单分区扫描->

    5.1/ 5.2对比,可以理解实际操作,rebuild online为什么一个多小时,rebuild 几分钟,全表扫描,数据量大差异越大

    5.3rebuild 普通堆表、Global索引
    explain plan for
    alter index scott.t_ind rebuild;
    select * from table(dbms_xplan.display);
    --------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    --------------------------------------------------------------------------------
    | 0 | ALTER INDEX STATEMENT | | 500K| 2441K| 402 (1)| 00:00:05 |
    | 1 | INDEX BUILD NON UNIQUE| T_IND | | | | |
    | 2 | SORT CREATE INDEX | | 500K| 2441K| | |
    | 3 | INDEX FAST FULL SCAN| T_IND | | | | |
    --------------------------------------------------------------------------------

    explain plan for
    alter index scott.t_ind rebuild online;
    select * from table(dbms_xplan.display);
    --------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    --------------------------------------------------------------------------------
    | 0 | ALTER INDEX STATEMENT | | 500K| 2441K| 402 (1)| 00:00:05 |
    | 1 | INDEX BUILD NON UNIQUE| T_IND | | | | |
    | 2 | SORT CREATE INDEX | | 500K| 2441K| | |
    | 3 | TABLE ACCESS FULL | T1 | 500K| 2441K| 402 (1)| 00:00:05 |
    --------------------------------------------------------------------------------

    对于普通表,全局索引而言,完全可以采用rebuild online操作,因为执行计划只有一条路!效率无明显差异


    5.4rebuild 分区表、Global索引、Global索引 online对比
    #drop index scott.t_p_ind;
    #create index t_p_ind on t(id) local;
    #create index scott.t_p_ind on scott.t(id);

    explain plan for
    alter index scott.t_p_ind rebuild;
    select * from table(dbms_xplan.display);
    ----------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
    ----------------------------------------------------------------------------------
    | 0 | ALTER INDEX STATEMENT | | 500K| 2441K| 400 (1)| 00:00:05 |
    | 1 | INDEX BUILD NON UNIQUE| T_P_IND | | | | |
    | 2 | SORT CREATE INDEX | | 500K| 2441K| | |
    | 3 | INDEX FAST FULL SCAN| T_P_IND | | | | |
    ----------------------------------------------------------------------------------

    explain plan for
    alter index scott.t_p_ind rebuild online;
    select * from table(dbms_xplan.display);
    --------------------------------------------------------------------------------------------------
    | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
    --------------------------------------------------------------------------------------------------
    | 0 | ALTER INDEX STATEMENT | | 500K| 2441K| 400 (1)| 00:00:05 | | |
    | 1 | INDEX BUILD NON UNIQUE| T_P_IND | | | | | | |
    | 2 | SORT CREATE INDEX | | 500K| 2441K| | | | |
    | 3 | PARTITION HASH ALL | | 500K| 2441K| 400 (1)| 00:00:05 | 1 | 4 |
    | 4 | TABLE ACCESS FULL | T | 500K| 2441K| 400 (1)| 00:00:05 | 1 | 4 |
    --------------------------------------------------------------------------------------------------
    分区表,全局索引rebuild online操作时,会对所有分区hash查询 ,此处未明显判断是否有影响,暂存

    结论,在对大的分区表索引进行重建,可以先尝试使用rebuild 而不加online,除非业务确实繁忙,其它场景可直接使用rebuild online 重建即可


    6.0 使用10046 进行分区索引的重建
    使用分区索引rebuild
    分区索引rebuild online

    #drop index scott.t_p_ind;
    #create index scott.t_p_ind on scott.t(id) local;
    查询分区表、分区段、块ID
    select
    t.segment_name,
    t.partition_name,
    t.BLOCK_ID,(t.BLOCKS + t.BLOCK_ID -1) "MAX_BLOCK_ID"
    from sys.dba_extents t,dba_tab_partitions p
    where t.PARTITION_NAME=p.partition_name and p.TABLE_OWNER='SCOTT' and p.table_name='T';
    SEGMENT_NA PARTITION_NAME BLOCK_ID MAX_BLOCK_ID
    ---------- ------------------------------ ---------- ------------
    T SYS_P109 714368 715391
    T SYS_P110 715392 716415
    T SYS_P111 716416 717439
    T SYS_P112 717440 718463

    查询分区索引、分区索引段
    select index_name,s.partition_name,SEGMENT_NAME,HEADER_FILE,HEADER_BLOCK,HEADER_BLOCK+BLOCKS-1 "MAX_BLOCK" from dba_segments s,user_ind_partitions p where p.PARTITION_NAME=s.PARTITION_NAME and p.INDEX_NAME='T_P_IND';

    INDEX_NAME PARTITION_ SEGMENT_NA HEADER_FILE HEADER_BLOCK MAX_BLOCK
    ---------- ---------- ---------- ----------- ------------ ----------
    T_P_IND SYS_P124 T_P_IND 4 722962 723345
    T_P_IND SYS_P123 T_P_IND 4 686610 686993
    T_P_IND SYS_P122 T_P_IND 4 725266 725649
    T_P_IND SYS_P121 T_P_IND 4 154 537


    alter session set events '10046 trace name context forever, level 12';
    alter index t_p_ind rebuild partition SYS_P121;
    exit

    找出部分记录进行注释说明,不能确保正确,仅限个人理解
    --第一部分,SQL语句的执行,获取数据字典表信息,执行计划生成 !!!没看明白,暂时放弃
    select u.name, o.name, o.namespace, o.type#, decode(bitand(i.property,1024),0,0,1), o.obj# from ind$ i,obj$ o,user$ u where i.obj#=:1 and o.obj#=i.bo# and o.owner#=u.user#
    FETCH
    STATNESTED LOOPS
    STATNESTED LOOPS
    STAT'TABLE ACCESS BY INDEX ROWID IND$
    STAT'INDEX UNIQUE SCAN I_IND1
    STAT'TABLE ACCESS BY INDEX ROWID OBJ$ alter session set events '10046 trace name context forever, level 12';
    STAT'INDEX RANGE SCAN I_OBJ1 alter index object_idx rebuild online;
    STAT'TABLE ACCESS CLUSTER USER$
    STAT'INDEX UNIQUE SCAN I_USER#


    alter session set events '10046 trace name context forever, level 12';
    alter index t_p_ind rebuild partition SYS_P121 online;
    exit

    !!暂且放弃10046

  • 相关阅读:
    firefox上网问题解决
    ubuntu内核的编译安装
    ubuntu常用命令
    source insight 添加文件类型
    ubuntu版本查看命令
    百年孤独与拉丁美洲历史--转载
    Guess Number Higher or Lower II--困惑
    Symmetric Tree
    一棵开花的树
    yii2 mysql数据库读写分离配置
  • 原文地址:https://www.cnblogs.com/lvcha001/p/9695254.html
Copyright © 2011-2022 走看看