技术开发 频道

关于复合分区索引状态的研究

  【IT168 技术】作者看到有网友问关于符复合区索引状态的探索,引起了兴趣,因为到目前为止,作者用到的复合分区的情况比较少。遂测试了一下。为了得到测试目的,作者建立了一个range_list的复合分区表zrp_part。

  建表语句如下:

SQL> create table zrp_part (
  2     region number(3),
  3     proc_no number(2)
  4     )
  5     partition by range (region)
  6     subpartition by list (proc_no)
  7           subpartition template
  8           ( subpartition proc_1  values(1),
  9             subpartition proc_2 values(2),
10             subpartition proc_max values(DEFAULT)           
11            )
12        (  partition zrp_part_010 values less than(20),
13           partition zrp_part_020 values less than (30),
14           partition zrp_part_max values less than (MAXVALUE)
15        );
表已创建。
SQL>
然后再建一个LOCAL索引
SQL> create index inx_zrp_test on zrp_part (region,proc_no)   
  2     LOCAL
  3     (PARTITION zrp_part_010,
  4      PARTITION zrp_part_020,
  5      PARTITION zrp_part_max
  6  );
索引已创建。
SQL>

  查看此时的索引状态

1)dba_indexes 视图

SQL> select index_name,status from dba_indexes where index_name='INX_ZRP_TEST';

INX_ZRP_TEST                   N/A
2) dba_ind_partitions视图
SQL> select index_name,partition_name,status from user_ind_partitions where index_name='INX_ZRP_TEST';

INX_ZRP_TEST                   ZRP_PART_010                   N/A
INX_ZRP_TEST                   ZRP_PART_020                   N/A
INX_ZRP_TEST                   ZRP_PART_MAX                   N/A
3)dba_ind_subpartitions视图
SQL> select index_name ,partition_name,subpartition_name,status from user_ind_subpartitions where index_name='INX_ZRP_TEST';

INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_1            USABLE
INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_2            USABLE
INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_MAX          USABLE
INX_ZRP_TEST                   ZRP_PART_020   ZRP_PART_020_PROC_1            USABLE
INX_ZRP_TEST                   ZRP_PART_020   ZRP_PART_020_PROC_2            USABLE
INX_ZRP_TEST                   ZRP_PART_020   ZRP_PART_020_PROC_MAX          USABLE
INX_ZRP_TEST                   ZRP_PART_MAX   ZRP_PART_MAX_PROC_1            USABLE
INX_ZRP_TEST                   ZRP_PART_MAX   ZRP_PART_MAX_PROC_2            USABLE
INX_ZRP_TEST                   ZRP_PART_MAX   ZRP_PART_MAX_PROC_MAX          USABLE

SQL>
插入几条数据验证一下
SQL> insert into zrp_part values(10,1);

已创建 1 行。

SQL> insert into zrp_part values(10,2);

已创建 1 行。

SQL> insert into zrp_part values(20,1);

已创建 1 行。

SQL> insert into zrp_part values(20,2);

已创建 1 行。

SQL> commit;
提交完成。
提交完成。
SQL> select * from zrp_part;

        10          1
        10          2
        20          1
        20          2

SQL>

  下面我们看看数据都存到哪个分区里去了(这是为了让后面的测试更有说服力)

SQL> select * from zrp_part partition(zrp_part_010);

        10          1
        10          2

SQL> select * from zrp_part partition(zrp_part_020);

        20          1
        20          2

SQL> select * from zrp_part partition(zrp_part_max);
未选定行
SQL>
SQL> select * from zrp_part subpartition (zrp_part_010_proc_1);

        10          1

SQL> select * from zrp_part subpartition (zrp_part_010_proc_2);

        10          2

SQL> select * from zrp_part subpartition (zrp_part_020_proc_1);

        20          1

SQL> select * from zrp_part subpartition (zrp_part_020_proc_2);

        20          2
SQL> select * from zrp_part subpartition (zrp_part_max_proc_1);
未选定行
SQL> select * from zrp_part subpartition (zrp_part_max_proc_2);
未选定行
SQL>

  可以看到,我们的数据按照预期的分区分别插入到了正确的地方。

  下面我们做一个数据检索,看看Oracle 的执行计划是如何的

SQL> select * from zrp_part where region=10 and proc_no=1;

SQL> select * from zrp_part where region=10 and proc_no=1;

执行计划
----------------------------------------------------------
Plan hash value: 61450464

-------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |    26 |     1   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|              |     1 |    26 |     1   (0)| 00:00:01 |     1 |     1 |
|   2 |   PARTITION LIST SINGLE|              |     1 |    26 |     1   (0)| 00:00:01 |   KEY |   KEY |
|*  3 |    INDEX RANGE SCAN    | INX_ZRP_TEST |     1 |    26 |     1   (0)| 00:00:01 |     1 |     1 |
-------------------------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("REGION"=10 AND "PROC_NO"=1)

Note
-----
   - dynamic sampling used for this statement

SQL>

  可以看到此时用上了分区索引,并进行了索引范围扫描。

  下面我手工将索引的状态修改为UNUSABLE,模拟索引破坏的情况(比如移动分区的情况)

SQL> alter index inx_zrp_test unusable;

索引已更改。

SQL>

再看索引的状态
1)dba_indexes 视图

SQL> select index_name,status from dba_indexes where index_name='INX_ZRP_TEST';

INX_ZRP_TEST                   N/A

2) dba_ind_partitions视图
SQL> select index_name,partition_name,status from user_ind_partitions where index_name='INX_ZRP_TEST';

INX_ZRP_TEST                   ZRP_PART_010                   N/A
INX_ZRP_TEST                   ZRP_PART_020                   N/A
INX_ZRP_TEST                   ZRP_PART_MAX                   N/A

3)dba_ind_subpartitions视图

SQL> select index_name ,partition_name,subpartition_name,status from user_ind_subpartitions where index_name='INX_ZRP_TEST';

INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_1            UNUSABLE
INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_2            UNUSABLE
INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_MAX          UNUSABLE
INX_ZRP_TEST                   ZRP_PART_020   ZRP_PART_020_PROC_1            UNUSABLE
INX_ZRP_TEST                   ZRP_PART_020   ZRP_PART_020_PROC_2            UNUSABLE
INX_ZRP_TEST                   ZRP_PART_020   ZRP_PART_020_PROC_MAX          UNUSABLE
INX_ZRP_TEST                   ZRP_PART_MAX   ZRP_PART_MAX_PROC_1            UNUSABLE
INX_ZRP_TEST                   ZRP_PART_MAX   ZRP_PART_MAX_PROC_2            UNUSABLE
INX_ZRP_TEST                   ZRP_PART_MAX   ZRP_PART_MAX_PROC_MAX          UNUSABLE

SQL>

再做数据检索的验证(还是刚才那个检索语句)

SQL> select * from zrp_part where region=10 and proc_no=1;

执行计划
----------------------------------------------------------
Plan hash value: 3999291197
---------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time  | Pstart| Pstop |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |    26 |    27   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|          |     1 |    26 |    27   (0)| 00:00:01 |     1 |     1 |
|   2 |   PARTITION LIST SINGLE|          |     1 |    26 |    27   (0)| 00:00:01 |   KEY |   KEY |
|*  3 |    TABLE ACCESS FULL   | ZRP_PART |     1 |    26 |    27   (0)| 00:00:01 |     1 |     1 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("REGION"=10)

Note
-----
   - dynamic sampling used for this statement

SQL>

  很明显,此时只能是走全表扫描了。

  下面依次按照子分区来修复索引

  SQL> alter index INX_ZRP_TEST rebuild subpartition ZRP_PART_010_PROC_1;

  索引已更改。

SQL> select * from zrp_part where region=10 and proc_no=1;

执行计划
----------------------------------------------------------
Plan hash value: 3999291197

---------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time  | Pstart| Pstop |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |    26 |    27   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|          |     1 |    26 |    27   (0)| 00:00:01 |     1 |     1 |
|   2 |   PARTITION LIST SINGLE|          |     1 |    26 |    27   (0)| 00:00:01 |   KEY |   KEY |
|*  3 |    TABLE ACCESS FULL   | ZRP_PART |     1 |    26 |    27   (0)| 00:00:01 |     1 |     1 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("REGION"=10)

Note
-----
   - dynamic sampling used for this statement

SQL>

SQL> select * from zrp_part subpartition (zrp_part_010_proc_1);
     10          1

SQL> select index_name ,partition_name,subpartition_name,status from user_ind_subpartitions where index_name='INX_ZRP_TEST' and status='USABLE';

INX_ZRP_TEST                   ZRP_PART_010    ZRP_PART_010_PROC_1            USABLE

SQL>   


SQL> alter index inx_zrp_test rebuild subpartition zrp_part_010_proc_2;

索引已更改。

SQL> select * from zrp_part where region=10 and proc_no=1;

执行计划
----------------------------------------------------------
Plan hash value: 3999291197

---------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time  | Pstart| Pstop |
---------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |    26 |    27   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|          |     1 |    26 |    27   (0)| 00:00:01 |     1 |     1 |
|   2 |   PARTITION LIST SINGLE|          |     1 |    26 |    27   (0)| 00:00:01 |   KEY |   KEY |
|*  3 |    TABLE ACCESS FULL   | ZRP_PART |     1 |    26 |    27   (0)| 00:00:01 |     1 |     1 |
---------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("REGION"=10)

Note
-----
   - dynamic sampling used for this statement

SQL> alter index inx_zrp_test rebuild subpartition zrp_part_010_proc_max;

索引已更改。

SQL> select * from zrp_part where region=10 and proc_no=1;

执行计划
----------------------------------------------------------
Plan hash value: 61450464

-------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |              |     1 |    26 |     1   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE SINGLE|              |     1 |    26 |     1   (0)| 00:00:01 |     1 |     1 |
|   2 |   PARTITION LIST SINGLE|              |     1 |    26 |     1   (0)| 00:00:01 |   KEY |   KEY |
|*  3 |    INDEX RANGE SCAN    | INX_ZRP_TEST |     1 |    26 |     1   (0)| 00:00:01 |     1 |     1 |
-------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("REGION"=10 AND "PROC_NO"=1)

Note
-----
   - dynamic sampling used for this statement

SQL>

SQL> select index_name ,partition_name,subpartition_name,status from user_ind_subpartitions where index_name='INX_ZRP_TEST' and status='USABLE';

INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_1            USABLE
INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_2            USABLE
INX_ZRP_TEST                   ZRP_PART_010   ZRP_PART_010_PROC_MAX          USABLE

SQL>

  到这个时候,第一个分区的所有子分区的索引全部rebuild 了,所以索引就用了,而其他分区的还不行,

  还需要修复后才可以。我就不写了。累死我了。

  小结一下吧:根据测试的情况来看,复合分区索引和一般的分区索引性质是一样的,只不过大家访问的时候需要换成

  另外的视图而已了。

  值得一提的是:

   SQL> alter index inx_zrp_test rebuild partition zrp_part_010;
   alter index inx_zrp_test rebuild partition zrp_part_010
第 1 行出现错误:
   ORA-14287: 不能 REBUILD (重建) 组合范围分区的索引的分区
   SQL>

  请大家要注意。

1
相关文章