ITPub博客

首页 > 数据库 > Oracle > Oracle 12c新特性维护表分区Global Index不失效

Oracle 12c新特性维护表分区Global Index不失效

原创 Oracle 作者:你好我是李白 时间:2020-01-09 12:51:29 1 删除 编辑

1.新特性官方文档说明

这个特性为:Oracle 12c Release 1 New Feature
详情可参考官方文档:Database VLDB and Partitioning Guide

新特性限制

Asynchronous Global Index Maintenance for Dropping and Truncating Partitions
The partition maintenance operations DROP PARTITION and TRUNCATE PARTITION are optimized by making the index maintenance for metadata only.
Asynchronous global index maintenance for DROP and TRUNCATE is performed by default; however, the UPDATE INDEXES clause is still required for backward compatibility.
The following list summarizes the limitations of asynchronous global index maintenance:
* Only performed on heap tables
* No support for tables with object types
* No support for tables with domain indexes
* Not performed for the user SYS

 新特性四种手动维护办法

* Maintenance operations on indexes can be performed with the automatic scheduler job SYS.PMO_DEFERRED_GIDX_MAINT_JOB to clean up all global indexes. This job is scheduled to run at 2:00 A.M. on a daily basis by default. You can run this job at any time using DBMS_SCHEDULER.RUN_JOB if you want to proactively clean up the indexes. You can also modify the job to run with a different schedule based on your specific requirements. However, Oracle recommends that you do not drop the job.
You can also force cleanup of an index needing maintenance using one of the following options:
* DBMS_PART.CLEANUP_GIDX - This PL/SQL procedure gathers the list of global indexes in the system that may require cleanup and runs the operations necessary to restore the indexes to a clean state.
* ALTER INDEX REBUILD [PARTITION] – This SQL statement rebuilds the entire index or index partition as is done in releases previous to Oracle Database 12c Release 1 (12.1). The resulting index (partition) does not contain any stale entries.
* ALTER INDEX [PARTITION] COALESCE CLEANUP – This SQL statement cleans up any orphaned entries in index blocks.

2.测试 

(1)创建测试表以及插入数据

# 创建测试表
TEST@czhpdb1 > create table test_part (id number,name varchar2(30))
  2  partition by range(id)
  3  (
  4  partition p1 values less than (1000),
  5  partition p2 values less than (2000),
  6  partition p3 values less than (3000),
  7  partition p4 values less than (4000),
  8  partition p5 values less than (maxvalue)
  9  );
# 插入测试数据
TEST@czhpdb1 > declare
id number;
begin
for i in 1..6000 loop
    id:=i;
    insert into test_part values(id,'nihaoma');
end loop;
commit;
end;
/
TEST@czhpdb1 > select count(*) from test_part;
                                COUNT(*)
----------------------------------------
                                    6000
# 创建global index
                                    
TEST@czhpdb1 > create index idx_test_part on test_part(id) global indexing full;
Index created.
                                 
# 查询global index状态                                    
TEST@czhpdb1 > select table_name,index_name,status,num_rows from user_indexes where table_name='TEST_PART';
TABLE_NAME      INDEX_NAME           STATUS                                     NUM_ROWS
--------------- -------------------- ---------- ----------------------------------------
TEST_PART       IDX_TEST_PART        VALID                                          6000
# 收集表统计信息
TEST@czhpdb1 > exec dbms_stats.gather_table_stats(ownname => 'TEST',tabname => 'TEST_PART');
PL/SQL procedure successfully completed.
# 查看表分区状态
TEST@czhpdb1 > select table_name,partition_name,num_rows,blocks from user_tab_partitions where table_name='TEST_PART';
TABLE_NAME      PARTITION_NAME                                  NUM_ROWS      BLOCKS
--------------- --------------- ---------------------------------------- -----------
TEST_PART       P1                                                   999        1006
TEST_PART       P2                                                  1000        1006
TEST_PART       P3                                                  1000        1006
TEST_PART       P4                                                  1000        1006
TEST_PART       P5                                                  2001        1006

(2)不使用新特性删除分区

# 删除分区p1
TEST@czhpdb1 > alter table test_part drop partition p1;
Table altered.
# 查看global index状态,可以看到global index变为unusable状态
TEST@czhpdb1 > select table_name,index_name,status,num_rows from user_indexes where table_name='TEST_PART';
TABLE_NAME      INDEX_NAME           STATUS                                     NUM_ROWS
--------------- -------------------- ---------- ----------------------------------------
TEST_PART       IDX_TEST_PART        UNUSABLE                                       6000
# 可以看到,索引变为unusable状态之后,Oracle会将索引段删除
TEST@czhpdb1 > select segment_name,sum(bytes/1024) KB from user_segments where segment_name='IDX%' group by segment_name;
no rows selected  
  
# 重建索引,使索引状态正常
TEST@czhpdb1 > alter index idx_test_part rebuild online;
Index altered.
TEST@czhpdb1 > select table_name,index_name,status,num_rows from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS
---------------------------------------- -------------------- ---------- ----------------------------------------
TEST_PART                                IDX_TEST_PART        VALID                                          5001

(3)使用新特性update indexes子句

# update indexes更新所有索引,global 或者local,而当使用update indexes更新global index时,不能指定子句,
# update global indexes只能用于global indexes
TEST@czhpdb1 > alter table test_part drop partition p2 update indexes;      
Table altered.
# 可以看到索引并没有失效,但是NUM_ROWS并未发生改变,也就是索引并未被实时更新
TEST@czhpdb1 > select table_name,index_name,status,num_rows from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS
---------------------------------------- -------------------- ---------- ----------------------------------------
TEST_PART                                IDX_TEST_PART        VALID                                          5001
# 可以看到产生了延迟GLOBAL INDEX MAINTAINE的定时任务,默认凌晨两点开始自动执行维护global index
col job_name for a50
col LAST_START_DATE for a40
col NEXT_RUN_DATE for a40
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                        06-JAN-20 03.06.37.673278 AM PST8PDT     07-JAN-20 02.00.00.679539 AM PST8PDT   
# user_indexes视图orphaned_entries字段标识global index是否包含索引延迟维护的过期条目
TEST@czhpdb1 > select table_name,index_name,status,num_rows,orphaned_entries from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS ORPHANED_
---------------------------------------- -------------------- ---------- ---------------------------------------- ---------
TEST_PART                                IDX_TEST_PART        VALID                                          5001 YES

(4)手工维护延迟索引维护global index

如果需要,也可以通过如下四种办法手工维护延迟维护global index。

方法1:DBMS_PART.CLEANUP_GIDX

# 通过调用系统包DBMS_PART.CLEANUP_GIDX
col job_name for a50
col LAST_START_DATE for a40
col NEXT_RUN_DATE for a40
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                        06-JAN-20 03.06.37.673278 AM PST8PDT     07-JAN-20 02.00.00.679539 AM PST8PDT   
SYS@czh19c > exec DBMS_PART.CLEANUP_GIDX('TEST','TEST_PART');
PL/SQL procedure successfully completed.
TEST@czhpdb1 > select table_name,index_name,status,num_rows,orphaned_entries from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS ORPHANED_
---------------------------------------- -------------------- ---------- ---------------------------------------- ---------
TEST_PART                                IDX_TEST_PART        VALID                                          5001 NO

方法2:dbms_scheduler.run_job

# 使用sys连接数据库时,一定要注意切换pdb,只有切换到正确的pdb,才能正确的执行调度定时任务完成相应维护操作
SYS@czh19c > alter session set container=czhpdb1;
Session altered.
SYS@czh19c > show pdbs;
                                  CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------------------------------------- ------------------------------ ---------- ----------
                                       3 CZHPDB1                        READ WRITE NO
                                       
# 查询DBA_SCHEDULER_JOBS,查看调度任务
SYS@czh19c > col job_name for a50
SYS@czh19c > col LAST_START_DATE for a40
SYS@czh19c > col NEXT_RUN_DATE for a40
SYS@czh19c > 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                        06-JAN-20 03.06.37.606301 AM PST8PDT     07-JAN-20 02.00.00.609298 AM PST8PDT
# 手工执行调度任务
SYS@czh19c > exec dbms_scheduler.run_job('PMO_DEFERRED_GIDX_MAINT_JOB');
PL/SQL procedure successfully completed.
# 查看global index状态,已经被维护
TEST@czhpdb1 > select table_name,index_name,status,num_rows,orphaned_entries from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS ORPHANED_
---------------------------------------- -------------------- ---------- ---------------------------------------- ---------
TEST_PART                                IDX_TEST_PART        VALID                                          5001 NO

方法3:重建索引

# 可以rebuild启用并行parallel,rebuild完毕之后,使用alter index no paralle,关闭并行度
TEST@czhpdb1 > alter index idx_test_part rebuild online;
Index altered.
TEST@czhpdb1 > select table_name,index_name,status,num_rows,orphaned_entries from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS ORPHANED_
---------------------------------------- -------------------- ---------- ---------------------------------------- ---------
TEST_PART                                IDX_TEST_PART        VALID                                         10003 NO

方法四:coalesce cleanup

# COALESCE
# Specify this clause to merge the contents of index partition blocks where possible # to free blocks for reuse.
# CLEANUP
# Specify CLEANUP to remove orphaned index entries for records that were previously
# dropped or truncated by a table partition maintenance operation.
# To determine whether an index partition contains orphaned index entries, you can
# query the ORPHANED_ENTRIES column of the USER_, DBA_, ALL_PART_INDEXES
# data dictionary views. Refer to Oracle Database Reference for more information
TEST@czhpdb1 > alter index idx_test_part coalesce cleanup;
Index altered.
TEST@czhpdb1 > select table_name,index_name,status,num_rows,orphaned_entries from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS ORPHANED_
---------------------------------------- -------------------- ---------- ---------------------------------------- ---------
TEST_PART                                IDX_TEST_PART        VALID                                         10003 NO

(5)收集索引统计信息

# 手工维护索引之后,索引统计信息可能不准确,建议手动收集索引统计信息
TEST@czhpdb1 > exec dbms_stats.gather_index_stats('TEST','IDX_TEST_PART');
PL/SQL procedure successfully completed.
TEST@czhpdb1 > select table_name,index_name,status,num_rows,orphaned_entries from user_indexes where table_name='TEST_PART';
TABLE_NAME                               INDEX_NAME           STATUS                                     NUM_ROWS ORPHANED_
---------------------------------------- -------------------- ---------- ---------------------------------------- ---------
TEST_PART                                IDX_TEST_PART        VALID                                          9003 NO


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/31439444/viewspace-2672632/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
我们不比前人聪明,但是我们会在量变到质变的过程中有些机会重新访问前人没有机会解决的问题。

注册时间:2017-02-28

  • 博文量
    129
  • 访问量
    164279