[20130815]12c Asynchronous Global Index Maintenance Part II.txt

[20130815]12c Asynchronous Global Index Maintenance Part II.txt

参考链接:
http://richardfoote.wordpress.com/2013/08/06/12c-asynchronous-global-index-maintenance-part-ii-the-space-between/

更多的是重复作者的测试,加深理解:

1.测试环境:

SQL> @ver
BANNER                                                                               CON_ID
-------------------------------------------------------------------------------- ----------
Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production              0

2.测试建立:
建立测试数据参考[20130811]12c Asynchronous Global Index Maintenance Part I .txt。
SQL> create table muse (id number, code number, name varchar2(30))
partition by range (id)
(partition muse1 values less than (1000001),
partition muse2 values less than (2000001),
partition muse3 values less than (maxvalue));

SQL> insert into muse
select rownum, mod(rownum,100000), 'DAVID BOWIE' from
(select 1 from dual connect by level (select 1 from dual connect by level
3000000 rows created.

SQL> commit;
Commit complete.

SQL> create index muse_id_i on muse(id);
Index created.

SQL> create index muse_code_i on muse(code) global partition by range(code)
(partition code_p1 values less than (50000),
partition code_p2 values less than (maxvalue));
Index created.

SQL> exec dbms_stats.gather_table_stats(ownname=>user, tabname=>'MUSE', cascade=>true, estimate_percent=>null, method_opt=>'FOR ALL COLUMNS SIZE 1');
PL/SQL procedure successfully completed.

SQL> alter table muse drop partition muse1 update global indexes;
Table altered.

SQL> select index_name, null partition_name, num_rows, s.blocks, leaf_blocks, status, orphaned_entries
from dba_indexes i, dba_segments s where i.index_name = s.segment_name and table_name='MUSE' and partitioned = 'NO'
union
select index_name, i.partition_name, num_rows, s.blocks, leaf_blocks, status, orphaned_entries
from dba_ind_partitions i, dba_segments s where i.partition_name = s.partition_name and index_name like 'MUSE%';
INDEX_NAME           PARTITION_NAME         NUM_ROWS     BLOCKS LEAF_BLOCKS STATUS   ORPHANED_ENTRIES
-------------------- -------------------- ---------- ---------- ----------- -------- --------------------
MUSE_CODE_I          CODE_P1                 1500000       4224        4135 USABLE   YES
MUSE_CODE_I          CODE_P2                 1500000       4352        4177 USABLE   YES
MUSE_ID_I                                    3000000       9216        8633 VALID    YES

3.我们转储索引信息看看。

SQL> select object_id,data_object_id,object_name from dba_objects where wner=user and object_name='MUSE_ID_I';
 OBJECT_ID DATA_OBJECT_ID OBJECT_NAME
---------- -------------- --------------------
     92925          92925 MUSE_ID_I

SQL> alter session set events 'immediate trace name treedump level 92925';

----- begin tree dump 太长截取前面1段。
branch: 0x2400dc3 37752259 (0: nrow: 14, level: 2)
   branch: 0x2404937 37767479 (-1: nrow: 673, level: 1)
      leaf: 0x2400dc4 37752260 (-1: nrow: 383 rrow: 383)
      leaf: 0x2400dc5 37752261 (0: nrow: 378 rrow: 378)
      leaf: 0x2400dc6 37752262 (1: nrow: 378 rrow: 378)
      leaf: 0x2400dc7 37752263 (2: nrow: 378 rrow: 378)
      leaf: 0x2400dc8 37752264 (3: nrow: 378 rrow: 378)
      leaf: 0x2400dc9 37752265 (4: nrow: 378 rrow: 378)
      ...

SQL> @dfb 2400dc4
old   2: dbms_utility.data_block_address_file(to_number('&1','xxxxxxxxxxxxxxxx')) rfile#,
new   2: dbms_utility.data_block_address_file(to_number('2400dc4','xxxxxxxxxxxxxxxx')) rfile#,
old   3: dbms_utility.data_block_address_block(to_number('&&1','xxxxxxxxxxxxxxxx')) block#
new   3: dbms_utility.data_block_address_block(to_number('2400dc4','xxxxxxxxxxxxxxxx')) block#
    RFILE#     BLOCK#
---------- ----------
         9       3524

SQL> alter system dump datafile 9 block 3524;
Block header dump:  0x02400dc4
 Object id on Block? Y
 seg/obj: 0x16afd  csc: 0x00.343e73  itc: 2  flg: E  typ: 2 - INDEX
     brn: 0  bdba: 0x2400dc0 ver: 0x01 opc: 0
     inc: 0  exflg: 0
 
 Itl           Xid                  Uba         Flag  Lck        Scn/Fsc
0x01   0x0000.000.00000000  0x00000000.0000.00  ----    0  fsc 0x0000.00000000
0x02   0xffff.000.00000000  0x00000000.0000.00  C---    0  scn 0x0000.00343e73
Leaf block dump
===============
header address 366895204=0x15de6064
kdxcolev 0
KDXCOLEV Flags = - - -
kdxcolok 0
kdxcoopc 0x80: pcode=0: iot flags=--- is converted=Y
kdxconco 2
kdxcosdc 0
kdxconro 383
kdxcofbo 802=0x322
kdxcofeo 1627=0x65b
kdxcoavs 825
kdxlespl 0
kdxlende 0
kdxlenxt 37752261=0x2400dc5
kdxleprv 0=0x0
kdxledsz 0
kdxlebksz 8036
row#0[8020] flag: -------, lock: 0, len=16
col 0; len 2; (2):  c1 02
col 1; len 10; (10):  00 01 6a fa 02 40 16 98 00 00
row#1[8004] flag: -------, lock: 0, len=16
col 0; len 2; (2):  c1 03
col 1; len 10; (10):  00 01 6a fa 02 40 16 98 00 01
....

--可以发现这些flag都没有删除标识。换一句话讲删除分区时这些键值对应的块都没有改动。

    We notice there are no deleted index entries, the index remains totally untouched by the drop table partition
operation. So the good news is that dropping/truncating a table partition while updating global indexes is extremely
fast and efficient while the indexes remain hunky dory as subsequent index range scans can ignore any rowids that don't
reference existing table partitions of interest.

    However, the bad news is that during subsequent index DML operations, Oracle does not know which index entries are
valid and which are not and so the space used by these "orphaned" index entries can not be automatically reclaimed and
reused as it can with conventionally deleted index entries. Therefore, we need some other way to clean out the orphaned
index entries.

    There are a number of possible ways to do this. One way is to simply rebuild the global index (or index partition):

4.如何利用这些块呢?

SQL> alter index muse_code_i rebuild partition code_p1;

SQL> select index_name, null partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_indexes i, dba_segments s where i.index_name = s.segment_name and table_name='MUSE' and partitioned = 'NO'
union
select index_name, i.partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_ind_partitions i, dba_segments s where i.partition_name = s.partition_name and index_name like 'MUSE%';
INDEX_NAME           PARTITION_NAME       ORPHANED_ENTRIES       NUM_ROWS     BLOCKS LEAF_BLOCKS STATUS
-------------------- -------------------- -------------------- ---------- ---------- ----------- --------
MUSE_CODE_I          CODE_P1              NO                      1000000       2816        2756 USABLE
MUSE_CODE_I          CODE_P2              YES                     1500000       4352        4177 USABLE
MUSE_ID_I                                 YES                     3000000       9216        8633 VALID

--可以发现现在PARTITION_NAME=CODE_P1的ORPHANED_ENTRIES = NO.

SQL> alter index muse_id_i coalesce cleanup;
Index altered.

SQL> select index_name, null partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_indexes i, dba_segments s where i.index_name = s.segment_name and table_name='MUSE' and partitioned = 'NO'
union
select index_name, i.partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_ind_partitions i, dba_segments s where i.partition_name = s.partition_name and index_name like 'MUSE%';
INDEX_NAME           PARTITION_NAME       ORPHANED_ENTRIES       NUM_ROWS     BLOCKS LEAF_BLOCKS STATUS
-------------------- -------------------- -------------------- ---------- ---------- ----------- --------
MUSE_CODE_I          CODE_P1              NO                      1000000       2816        2756 USABLE
MUSE_CODE_I          CODE_P2              YES                     1500000       4352        4177 USABLE
MUSE_ID_I                                 NO                      3000000       9216        8633 VALID
--可以发现现在索引MUSE_ID_I的ORPHANED_ENTRIES = NO.

做一次分析:
SQL> exec dbms_stats.gather_index_stats(ownname=>user, indname=>'MUSE_ID_I', estimate_percent=>null);

SQL> select index_name, null partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_indexes i, dba_segments s where i.index_name = s.segment_name and table_name='MUSE' and partitioned = 'NO'
union
select index_name, i.partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_ind_partitions i, dba_segments s where i.partition_name = s.partition_name and index_name like 'MUSE%';
INDEX_NAME           PARTITION_NAME       ORPHANED_ENTRIES       NUM_ROWS     BLOCKS LEAF_BLOCKS STATUS
-------------------- -------------------- -------------------- ---------- ---------- ----------- --------
MUSE_CODE_I          CODE_P1              NO                      1000000       2816        2756 USABLE
MUSE_CODE_I          CODE_P2              YES                     1500000       4352        4177 USABLE
MUSE_ID_I                                 NO                      2000000       9216        5849 VALID

--统计信息显示正确!

SQL> analyze index muse_id_i validate structure;

SQL> select name, lf_rows, del_lf_rows from index_stats;
NAME                    LF_ROWS DEL_LF_ROWS
-------------------- ---------- -----------
MUSE_ID_I               2000000           0
--DEL_LF_ROWS =0.

    Yet another possible option is to simply wait for the PMO_DEFERRED_GIDX_MAINT_JOB job to run (scheduled by default
during the 2am maintenance window) to clean out orphaned index entries from all currently impacted global indexes.  Yet
another alternative is to manually run the dbms_part.cleanup_gidx procedure which is in turn called by this job:

SQL> exec dbms_part.cleanup_gidx;
PL/SQL procedure successfully completed.

SQL> select index_name, null partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_indexes i, dba_segments s where i.index_name = s.segment_name and table_name='MUSE' and partitioned = 'NO'
union
select index_name, i.partition_name, orphaned_entries, num_rows, s.blocks, leaf_blocks, status
from dba_ind_partitions i, dba_segments s where i.partition_name = s.partition_name and index_name like 'MUSE%';
INDEX_NAME           PARTITION_NAME       ORPHANED_ENTRIES       NUM_ROWS     BLOCKS LEAF_BLOCKS STATUS
-------------------- -------------------- -------------------- ---------- ---------- ----------- --------
MUSE_CODE_I          CODE_P1              NO                      1000000       2816        2756 USABLE
MUSE_CODE_I          CODE_P2              NO                      1500000       4352        4177 USABLE
MUSE_ID_I                                 NO                      2000000       9216        5849 VALID

SQL> set autot traceonly ;
SQL> select * from muse where id between 42 and 420;
no rows selected
Execution Plan
----------------------------------------------------------
Plan hash value: 2515419874
------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                                  | Name      | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                           |           |     1 |    23 |     4   (0)| 00:00:01 |       |       |
|   1 |  TABLE ACCESS BY GLOBAL INDEX ROWID BATCHED| MUSE      |     1 |    23 |     4   (0)| 00:00:01 |     1 |     1 |
|*  2 |   INDEX RANGE SCAN                         | MUSE_ID_I |   253 |       |     3   (0)| 00:00:01 |       |       |
------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("ID">=42 AND "ID"--执行计划再没有filter条件。

5.总结一下:1.alter index muse_code_i rebuild partition code_p1;也就是rebuild重建。2.alter index muse_id_i coalesce cleanup;3.exec dbms_part.cleanup_gidx; 
时间: 2024-07-31 13:16:35

[20130815]12c Asynchronous Global Index Maintenance Part II.txt的相关文章

[20130815]12c Asynchronous Global Index Maintenance Part III.txt

[20130815]12c Asynchronous Global Index Maintenance Part III.txt 参考链接:http://richardfoote.wordpress.com/2013/08/07/12c-asynchronous-global-index-maintenance-part-iii-re-makere-model/ 更多的是重复作者的测试,加深理解: 1.测试环境: SQL> @ver BANNER                         

[20130812]12c Partial Indexes For Partitioned Tables Part II.txt

[20130812]12c Partial Indexes For Partitioned Tables Part II.txt 参考链接:http://richardfoote.wordpress.com/2013/07/12/12c-partial-indexes-for-partitioned-tables-part-ii-vanishing-act/ 更多的是重复作者的测试,加深理解: 1.测试环境: SQL> @ver BANNER                           

ORACLE 12C Partial Global/Local Indexes for Partitioned Tables

以前我有个想法,我只想对其中的某个或者某几个分区上创建索引,其他分区不想创建,在12C之前的版本,无论是Local还是Global index,都不能实现该需求,但是从ORACLE 12C开始引进了Partial Global/Local Indexes for Partitioned Tables,解决了该问题,可以在指定的分区上创建本地索引或者全局索引,主要语法是在表或者分区,子分区级别设置[INDEXING { ON | OFF }]创建测试表  代码如下 复制代码 CDB_PDB@CHF

[20130910]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED(补充).txt

[20130910]12C执行计划的TABLE ACCESS BY INDEX ROWID BATCHED(补充).txt 链接http://space.itpub.net/267265/viewspace-772371 写了12c下在范围扫描时可能出现的TABLE ACCESS BY INDEX ROWID BATCHED,这是一种新的执行方式,能够提高执行效率,特别在数据聚集很好的情况下. 既然是12c的一个特性应该有一个参数关闭这个特性.重复前面的例子: 1.建立测试环境: SCOTT@t

[20130918]12C表统计信息的在线收集.txt

[20130918]12C表统计信息的在线收集.txt 在12c以前,如果使用ctas建立表,并不会自动收集表的统计信息,12c开始CTAS和IAS操作会收集统计信息.但是不收集直方图信息.以及索引统计. 摘要:twp-bp-for-stats-gather-12c-1967354.pdfBest Practices for Gathering Optimizer Statistics with Oracle Database 12c P16-17页: Online statistics gat

[20160220]12c视图一些字段显示128列.txt

[20160220]12c视图一些字段显示128列.txt --今天在家里做一些测试时,无意中发现视图显示字段名index_name占用很大的宽度,仔细检查才发现视图里面的显示长度已经是128列. SYS@test> @ver1 PORT_STRING          VERSION     BANNER                                                                        CON_ID -----------------

[20130915]12c新特性 varchar2支持32K长度.txt

[20130915]12c新特性 varchar2支持32K长度.txt oracle 12c以前如果字符串长度超过4000,必须使用blob或者clob类型.12c开始支持超过4000的字符串长度,提高一些应用的灵活性,达到32K,避免一些字段定义为clob,blob类型,提高处理能力. 但是12c默认的方式不支持大于4000的字符串长度,必须经过一些步骤升级完成,自己测试如下: SYS@test> @ver BANNER                                    

[20130803]ORACLE 12C TOP N SQL实现分页功能.txt

[20130803]ORACLE 12C TOP N SQL实现分页功能.txt 参考链接:http://www.xifenfei.com/4257.html SQL> @verBANNER                                                                               CON_ID----------------------------------------------------------------------

[20131116]12c的EXTENDED VARCHAR2与CLOB字段.txt

[20131116]12c的EXTENDED VARCHAR2与CLOB字段.txt oracle 12c以前如果字符串长度超过4000,必须使用blob或者clob类型.12c开始支持超过4000的字符串长度,提高一些应用的灵活性,达到32K,避免一些字段定义为clob,blob类型,提高处理能力. 要支持这个特性,要执行 @?/rdbms/admin/utl32k.sql升级步骤.如果存在pdb库,还必须升级PDB$SEED,以及PDB数据库.参考链接:http://space.itpub.