当前位置: 首页 > Oracle, Oracle 12c > 正文

Oracle 12C新特性-分区表全局索引异步维护

在12C之前的版本,对分区表进行删除分区或者TRUNCATE分区,合并或者分裂分区,MOVE分区等DDL操作时,分区表上的全局索引会失效,通常要加上UPDATE GLOBAL INDEXES或者ONLINE关键字,可是加上这些关键字之后,本来很快的DDL操作可能就要花费很长的时间,而且还要面临锁的问题。

Oracle 12C推出了分区表全局索引异步维护特性,这个特性有效的解决了这个问题,在对分区表进行上述DDL操作时,既能快速完成操作,也能保证全局索引有效,然后通过调度JOB在固定的时候对全局索引进行维护。

其实在这个新特性实现之前,我们对分区表进行DDL操作,通常也是会选择一个业务相对比较空闲的时间来做,通常是后半夜加班来弄,有了这个新特性,就可以在白天选择一个业务相对空闲的时间来做,然后在夜间业务比较空闲的时候,让ORACLE通过JOB统一来维护全局索引。

下面是对这个特性的一些测试和验证。T_TEST表为本文测试表。

SQL> select TABLE_NAME,PARTITION_NAME,NUM_ROWS from user_tab_partitions where TABLE_NAME='T_TEST';

TABLE_NAME           PARTITION_NAME         NUM_ROWS
-------------------- -------------------- ----------
T_TEST               P1                      2894575
T_TEST               P2                      7545716
T_TEST               P3                      9883824
T_TEST               P4                      3242359

上面是这张表的数据分布情况,下面为这张表创建全局索引(GLOBAL INDEX)。

SQL> create index IX_CST_ID_01 on T_TEST01(CST_ID) GLOBAL INDEXING FULL;

Index created.
SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS
-------------------- -------------------- -------- ----------
T_TEST               IX_CST_ID            VALID      23566474

GLOBAL INDEXING FULL这种写法也是ORACLE 12C的新特性,叫做分区表局部分区索引,就是只在指定的个别分区上创建索引,其他分区不创建索引,具体可以看我BLOG的上一篇文章。

下面先删掉一个分区,不指定UPDATE INDEXES。

SQL> alter table T_TEST drop partition p3;      

Table altered.

SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS
-------------------- -------------------- -------- ----------
T_TEST               IX_CST_ID            UNUSABLE   23566474

SQL> alter index IX_CST_ID rebuild;

Index altered.

SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS
-------------------- -------------------- -------- ----------
T_TEST               IX_CST_ID            VALID      13682650

上面的实验可以看出,在不指定UPDATE INDEXES的情况下删除分区,全局索引立马失效。这和之前的版本没人什么区别,下面再看一下指定UPDATE INDEXES的情况下,删除分区是什么情况。

SQL> alter table T_TEST drop partition p2 update indexes;

Table altered.

SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS
-------------------- -------------------- -------- ----------
T_TEST               IX_CST_ID            VALID      13682650

可能在这里也看不出什么问题,因为指定了UPDATE INDEXES,索引没有失效这很正常,可是这个索引并没有被更新。首先,这个操作很快就完成了,可以通过时间来判断,还有就是索引的记录数没有变化,还有就是查询索引的大小会更直观的看到,索引的大小没变。

这就是这个特性的功能,索引没更新,但是索引还有效。在DBA_INDEXES、USER_INDEXES里的ORPHANED_ENTRIES字段,记录了这个索引是否被标记成待维护状态。

SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS,ORPHANED_ENTRIES from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS ORPHANED_ENTRIES
-------------------- -------------------- -------- ---------- --------------------
T_TEST               IX_CST_ID            VALID      13682650 YES

ORPHANED_ENTRIES字段为YES表示这个全局索引需要维护,默认在凌晨两点钟,会执行JOB对ORPHANED_ENTRIES为YES的全局索引进行统一的维护。可以从DBA_SCHEDULER_JOBS里查看到这个JOB的信息。

SQL> select JOB_NAME,LAST_START_DATE,NEXT_RUN_DATE from DBA_SCHEDULER_JOBS where JOB_NAME='PMO_DEFERRED_GIDX_MAINT_JOB';

JOB_NAME                    LAST_START_DATE                  NEXT_RUN_DATE
--------------------------- -------------------------------- --------------------------------
PMO_DEFERRED_GIDX_MAINT_JOB 16-MAY-18 02.00.02.514339 AM PRC 17-MAY-18 02.00.00.515395 AM PRC

这个时间可以根据数据库的空闲时段进行调整,默认是每天的凌晨两点钟执行。如果想要立即对这个索引进行维护,可以通过以下的方法立即对全局索引进行维护。

方法1:

SQL> exec DBMS_PART.CLEANUP_GIDX('DBDREAM','T_TEST');

PL/SQL procedure successfully completed.

方法2:

SQL> exec dbms_scheduler.run_job('PMO_DEFERRED_GIDX_MAINT_JOB');

PL/SQL procedure successfully completed.

方法3:

SQL> alter index IX_CST_ID_01 COALESCE CLEANUP;

Index altered.

方法4:

SQL> alter index IX_CST_ID_01 rebuild;

Index altered.

手动触发全局索引维护后,ORPHANED_ENTRIES字段会变成NO,这样在PMO_DEFERRED_GIDX_MAINT_JOB执行的时候,就不会再去维护这个全局索引了。

SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS,ORPHANED_ENTRIES from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS ORPHANED_ENTRIES
-------------------- -------------------- -------- ---------- --------------------
T_TEST               IX_CST_ID            VALID      13682650 NO

但是通过上面的方法去维护全局索引的时候,可能索引维护了,但是索引的统计信息并没有被收集,这时候最好是手动收集一下。

候最好是手动收集一下。
SQL> exec dbms_stats.gather_index_stats('DBDREAM','IX_CST_ID');

PL/SQL procedure successfully completed.
SQL> select TABLE_NAME,INDEX_NAME,STATUS,NUM_ROWS,ORPHANED_ENTRIES from user_indexes where TABLE_NAME='T_TEST';

TABLE_NAME           INDEX_NAME           STATUS     NUM_ROWS ORPHANED_ENTRIES
-------------------- -------------------- -------- ---------- --------------------
T_TEST               IX_CST_ID            VALID       6136934 NO

忘了收集也没太大的关系,如果没有禁用数据库统计信息收集的情况下,ORACLE会自动收集的,只是需要等到收集统计信息的任务执行的时候而已。

本文固定链接: https://www.dbdream.com.cn/2018/07/oracle-12c%e6%96%b0%e7%89%b9%e6%80%a7-%e5%88%86%e5%8c%ba%e8%a1%a8%e5%85%a8%e5%b1%80%e7%b4%a2%e5%bc%95%e5%bc%82%e6%ad%a5%e7%bb%b4%e6%8a%a4/ | 信春哥,系统稳,闭眼上线不回滚!

该日志由 dbdream 于2018年07月05日发表在 Oracle, Oracle 12c 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Oracle 12C新特性-分区表全局索引异步维护 | 信春哥,系统稳,闭眼上线不回滚!
关键字: , , ,

Oracle 12C新特性-分区表全局索引异步维护:等您坐沙发呢!

发表评论

快捷键:Ctrl+Enter