暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

通过交换分区的方式,归档历史数据到历史表

一、使用交换分区的场景

将数据归档至历史表,有以下需求

t1分区表中有p1,p2,p3分区,现在要将p1分区放到t1_bak分区表中的p1分区,可以通过交换分区的方式

1.将t1:p1分区和临时表t1_tmp进行交换

2.将t1_bak:p1分区和临时表t1_tmp进行交换

二、构建测试数据

create user zhang identified by zhang; grant connect,resource,unlimited tablespace to zhang; conn zhang/zhang -- 创建t1分区表 create table t1 ( id number, name varchar2(100), created_date date ) partition by range (created_date) ( partition p1 values less than (to_date('2025-02-01', 'yyyy-mm-dd')), partition p2 values less than (to_date('2025-03-01', 'yyyy-mm-dd')), partition p3 values less than (maxvalue) ); -- 创建t1_bak分区表 create table t1_bak( id number, name varchar2(100), created_date date ) partition by range (created_date) ( partition p1 values less than (to_date('2025-02-01', 'yyyy-mm-dd')), partition p2 values less than (to_date('2025-03-01', 'yyyy-mm-dd')), partition p3 values less than (maxvalue) ); -- 创建t1_tmp临时表 create table t1_tmp ( id number, name varchar2(100), created_date date ); -- 插入 1 万行数据到t1的分区 p1 begin for i in 1..10000 loop insert into t1 values (i, 'name' || i, to_date('2025-01-15', 'yyyy-mm-dd')); end loop; commit; end; / -- 插入 1 万行数据到t1的分区 p2 begin for i in 10001..20000 loop insert into t1 values (i, 'name' || i, to_date('2025-02-15', 'yyyy-mm-dd')); end loop; commit; end; / --创建索引 create index idx_t1_1 on t1(id); create index idx_t1_2 on t1(name) local; create index idx_t1_bak_1 on t1_bak(id); create index dix_t1_bak_2 on t1_bak(name) local; create index idx_t1_tmp on t1_tmp(name); --收集统计信息 exec dbms_stats.gather_table_stats('ZHANG','T1',method_opt=>'for all columns size auto',cascade=>true,granularity=>'all',no_invalidate=>false);

三、测试

交换其中一个分区

--检查交换前的全局索引和分区索引 SQL> @dtp Enter value for table_name: T1 old 1: SELECT TABLE_OWNER,TABLE_NAME,PARTITION_POSITION||':'||PARTITION_NAME PARTITION_NAME,HIGH_VALUE,INTERVAL,TABLESPACE_NAME,NUM_ROWS,BLOCKS,LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='&table_name' new 1: SELECT TABLE_OWNER,TABLE_NAME,PARTITION_POSITION||':'||PARTITION_NAME PARTITION_NAME,HIGH_VALUE,INTERVAL,TABLESPACE_NAME,NUM_ROWS,BLOCKS,LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='T1' TABLE_OWNER TABLE_NAME PARTITION_NAME HIGH_VALUE INTE TABLESPACE_NAME NUM_ROWS BLOCKS LAST_ANALYZED --------------- ---------------------- -------------------- -------------------------------------------------------------------------------- ---- ------------------ ------------ ----------- ---------------------- ZHANG T1 1:P1 TO_DATE(' 2025-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA NO USERS 10,000 1,006 20250212 11:07:33 ZHANG T1 2:P2 TO_DATE(' 2025-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA NO USERS 10,000 1,006 20250212 11:07:33 ZHANG T1 3:P3 MAXVALUE NO USERS 0 0 20250212 11:07:33 SQL> @dind Session altered. Enter value for table_name: T1 old 22: where table_name='&table_name' new 22: where table_name='T1' OWNER(IDX|TAB) TABLE_NAME INDEX_NAME INDEX_TYPE UNIQUENESS PRAT BLEVEL LEAF_BLOCKS DISTINCT_KEYS NUM_ROWS STATUS CF LOG PARA ORP BUFFER_ LAST_ANALYZED ---------------------- ------------------------- ------------------------- ----------- ----------- ----- ------ ----------- ------------- ------------ ----------- --------- --- ---- --- ------- ---------------------- ZHANG|ZHANG T1 IDX_T1_1 NORMAL NONUNIQUE NO 1 55 20000 20,000 VALID 75 YES 1|1 NO DEFAULT 20250212 11:07:33 ZHANG|ZHANG T1 IDX_T1_2 NORMAL NONUNIQUE YES 1 58 19958 20,000 N/A 1941 1|1 NO DEFAULT 20250212 11:07:33 SQL> @dip Enter value for table_name: T1 old 1: select INDEX_OWNER,INDEX_NAME,PARTITION_NAME,STATUS,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR,DISTINCT_KEYS,NUM_ROWS,LAST_ANALYZED from dba_ind_partitions where index_name IN (select index_name from dba_part_indexes where owner='ZHANG' and table_name='&table_name') order by 1,2,3 new 1: select INDEX_OWNER,INDEX_NAME,PARTITION_NAME,STATUS,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR,DISTINCT_KEYS,NUM_ROWS,LAST_ANALYZED from dba_ind_partitions where index_name IN (select index_name from dba_part_indexes where owner='ZHANG' and table_name='T1') order by 1,2,3 INDEX_OWNER INDEX_NAME PARTITION_NAME STATUS BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR DISTINCT_KEYS NUM_ROWS LAST_ANALYZED --------------- ------------------------------ ------------------------------ ---------- ------ ------------ ----------------- ------------- ------------ ---------------------- ZHANG IDX_T1_2 P1 USABLE 1 28 1902 10,000 10,000 20250212 11:07:33 ZHANG IDX_T1_2 P2 USABLE 1 30 39 10,000 10,000 20250212 11:07:33 ZHANG IDX_T1_2 P3 USABLE 0 0 0 0 0 20250212 11:07:33 --交换分区t1:p1到t1_tmp SQL> alter table t1 exchange partition p1 with table t1_tmp including indexes update global indexes; Table altered. --交换分区t1_tmp到t1_bak:p1 SQL> alter table t1_bak exchange partition p1 with table t1_tmp including indexes update global indexes; Table altered. --检查交换后的全局索引和分区索引 SQL> @dtp Enter value for table_name: T1 old 1: SELECT TABLE_OWNER,TABLE_NAME,PARTITION_POSITION||':'||PARTITION_NAME PARTITION_NAME,HIGH_VALUE,INTERVAL,TABLESPACE_NAME,NUM_ROWS,BLOCKS,LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='&table_name' new 1: SELECT TABLE_OWNER,TABLE_NAME,PARTITION_POSITION||':'||PARTITION_NAME PARTITION_NAME,HIGH_VALUE,INTERVAL,TABLESPACE_NAME,NUM_ROWS,BLOCKS,LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='T1' TABLE_OWNER TABLE_NAME PARTITION_NAME HIGH_VALUE INTE TABLESPACE_NAME NUM_ROWS BLOCKS LAST_ANALYZED --------------- ---------------------- -------------------- -------------------------------------------------------------------------------- ---- ------------------ ------------ ----------- ---------------------- ZHANG T1 1:P1 TO_DATE(' 2025-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA NO USERS 0 0 20250212 11:06:38 ZHANG T1 2:P2 TO_DATE(' 2025-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA NO USERS 10,000 1,006 20250212 11:07:33 ZHANG T1 3:P3 MAXVALUE NO USERS 0 0 20250212 11:07:33 SQL> @dind Session altered. Enter value for table_name: T1 old 22: where table_name='&table_name' new 22: where table_name='T1' OWNER(IDX|TAB) TABLE_NAME INDEX_NAME INDEX_TYPE UNIQUENESS PRAT BLEVEL LEAF_BLOCKS DISTINCT_KEYS NUM_ROWS STATUS CF LOG PARA ORP BUFFER_ LAST_ANALYZED ---------------------- ------------------------- ------------------------- ----------- ----------- ----- ------ ----------- ------------- ------------ ----------- --------- --- ---- --- ------- ---------------------- ZHANG|ZHANG T1 IDX_T1_1 NORMAL NONUNIQUE NO 1 55 20000 20,000 VALID 75 YES 1|1 NO DEFAULT 20250212 11:07:33 ZHANG|ZHANG T1 IDX_T1_2 NORMAL NONUNIQUE YES 1 58 19958 20,000 N/A 1941 1|1 NO DEFAULT 20250212 11:07:33 SQL> @dip Enter value for table_name: T1 old 1: select INDEX_OWNER,INDEX_NAME,PARTITION_NAME,STATUS,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR,DISTINCT_KEYS,NUM_ROWS,LAST_ANALYZED from dba_ind_partitions where index_name IN (select index_name from dba_part_indexes where owner='ZHANG' and table_name='&table_name') order by 1,2,3 new 1: select INDEX_OWNER,INDEX_NAME,PARTITION_NAME,STATUS,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR,DISTINCT_KEYS,NUM_ROWS,LAST_ANALYZED from dba_ind_partitions where index_name IN (select index_name from dba_part_indexes where owner='ZHANG' and table_name='T1') order by 1,2,3 INDEX_OWNER INDEX_NAME PARTITION_NAME STATUS BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR DISTINCT_KEYS NUM_ROWS LAST_ANALYZED --------------- ------------------------------ ------------------------------ ---------- ------ ------------ ----------------- ------------- ------------ ---------------------- ZHANG IDX_T1_2 P1 USABLE 0 0 0 0 0 20250212 11:06:38 ZHANG IDX_T1_2 P2 USABLE 1 30 39 10,000 10,000 20250212 11:07:33 ZHANG IDX_T1_2 P3 USABLE 0 0 0 0 0 20250212 11:07:33 SQL> @dtp Enter value for table_name: T1_BAK old 1: SELECT TABLE_OWNER,TABLE_NAME,PARTITION_POSITION||':'||PARTITION_NAME PARTITION_NAME,HIGH_VALUE,INTERVAL,TABLESPACE_NAME,NUM_ROWS,BLOCKS,LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='&table_name' new 1: SELECT TABLE_OWNER,TABLE_NAME,PARTITION_POSITION||':'||PARTITION_NAME PARTITION_NAME,HIGH_VALUE,INTERVAL,TABLESPACE_NAME,NUM_ROWS,BLOCKS,LAST_ANALYZED FROM DBA_TAB_PARTITIONS WHERE TABLE_NAME='T1_BAK' TABLE_OWNER TABLE_NAME PARTITION_NAME HIGH_VALUE INTE TABLESPACE_NAME NUM_ROWS BLOCKS LAST_ANALYZED --------------- ---------------------- -------------------- -------------------------------------------------------------------------------- ---- ------------------ ------------ ----------- ---------------------- ZHANG T1_BAK 1:P1 TO_DATE(' 2025-02-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA NO USERS 10,000 1,006 20250212 11:07:33 ZHANG T1_BAK 2:P2 TO_DATE(' 2025-03-01 00:00:00', 'SYYYY-MM-DD HH24:MI:SS', 'NLS_CALENDAR=GREGORIA NO USERS ZHANG T1_BAK 3:P3 MAXVALUE NO USERS SQL> @dind Session altered. Enter value for table_name: T1_BAK old 22: where table_name='&table_name' new 22: where table_name='T1_BAK' OWNER(IDX|TAB) TABLE_NAME INDEX_NAME INDEX_TYPE UNIQUENESS PRAT BLEVEL LEAF_BLOCKS DISTINCT_KEYS NUM_ROWS STATUS CF LOG PARA ORP BUFFER_ LAST_ANALYZED ---------------------- ------------------------- ------------------------- ----------- ----------- ----- ------ ----------- ------------- ------------ ----------- --------- --- ---- --- ------- ---------------------- ZHANG|ZHANG T1_BAK IDX_T1_BAK_1 NORMAL NONUNIQUE NO 1 0 0 0 VALID 0 YES 1|1 NO DEFAULT 20250211 22:00:06 ZHANG|ZHANG T1_BAK DIX_T1_BAK_2 NORMAL NONUNIQUE YES 0 0 0 0 N/A 0 1|1 NO DEFAULT 20250211 22:00:06 SQL> @dip Enter value for table_name: T1_BAK old 1: select INDEX_OWNER,INDEX_NAME,PARTITION_NAME,STATUS,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR,DISTINCT_KEYS,NUM_ROWS,LAST_ANALYZED from dba_ind_partitions where index_name IN (select index_name from dba_part_indexes where owner='ZHANG' and table_name='&table_name') order by 1,2,3 new 1: select INDEX_OWNER,INDEX_NAME,PARTITION_NAME,STATUS,BLEVEL,LEAF_BLOCKS,CLUSTERING_FACTOR,DISTINCT_KEYS,NUM_ROWS,LAST_ANALYZED from dba_ind_partitions where index_name IN (select index_name from dba_part_indexes where owner='ZHANG' and table_name='T1_BAK') order by 1,2,3 INDEX_OWNER INDEX_NAME PARTITION_NAME STATUS BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR DISTINCT_KEYS NUM_ROWS LAST_ANALYZED --------------- ------------------------------ ------------------------------ ---------- ------ ------------ ----------------- ------------- ------------ ---------------------- ZHANG DIX_T1_BAK_2 P1 USABLE 1 28 1902 10,000 10,000 20250212 11:07:33 ZHANG DIX_T1_BAK_2 P2 USABLE 0 0 0 0 0 20250211 13:22:23 ZHANG DIX_T1_BAK_2 P3 USABLE 0 0 0 0 0 20250211 13:22:23

四、测试结论

通过上述输出我们可以得出以下观点

  • t1:p1分区已正确交换至t1_bak.p1
  • t1和t1_bak的全局索引未失效(依赖于update global indexes参数)
  • t1和t1_bak的分区索引未失效(依赖于including indexes 参数)
  • 分区交换后dba_indexes的 orphaned_entries字段为NO,说明没有采用异步全局索引维护
  • 分区相关的统计信息正确交换,但是全局统计信息未更新,可以考虑交换完成后手工收集全局统计信息

五、注意事项

1.若中间表未建立对应的分区索引,则使用including indexes会提示ORA-14098

SQL> drop index idx_t1_tmp; Index dropped. SQL> alter table t1 exchange partition p1 with table t1_tmp including indexes update global indexes; alter table t1 exchange partition p1 with table t1_tmp including indexes update global indexes * ERROR at line 1: ORA-14098: index mismatch for tables in ALTER TABLE EXCHANGE PARTITION

2.若被交换的分区有DML操作,则会提示ORA-00054,DQL操作不影响

-- DML测试 -- 会话1 SQL> update t1 set name='zhang' where id=1500; 1 row updated. -- 会话2 SQL> alter table t1 exchange partition p1 with table t1_tmp including indexes update global indexes; alter table t1 exchange partition p1 with table t1_tmp including indexes update global indexes * ERROR at line 1: ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired -- DQL测试 -- 会话1 SQL> set feed only SQL> select * from t1 partition(p1) a,t1 partition(p1) b; -- 会话2 SQL> alter table t1 exchange partition p1 with table t1_tmp including indexes update global indexes; Table altered.

3.若需要交换的分区较多,并且实施过程中全局索引不需要使用,可以考虑不使用update global indexes参数,全部分区交换完成后进行全局索引的重建

alter table t1 exchange partition p1 with table t1_tmp including indexes; alter table t1_bak exchange partition p1 with table t1_tmp including indexes; alter index IDX_T1_1 rebuild online; --重建全局索引

4.全局统计信息未更新,可以考虑交换完成后手工收集全局统计信息

exec dbms_stats.gather_table_stats('ZHANG','T1',method_opt=>'for all columns size auto',cascade=>true,granularity=>'global',no_invalidate=>false); exec dbms_stats.gather_table_stats('ZHANG','T1_BAK',method_opt=>'for all columns size auto',cascade=>true,granularity=>'global',no_invalidate=>false);
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论