当前位置:操作系统 > Unix/Linux >>

怎么在线对表进行分区(How to perform online redefinition)

怎么在线对表进行分区(How to perform online redefinition)
 
之前同事做过一个表的在线分区,当时情况是这样的,有一个大表,每个月多要删除一个月的数据,当delete的时候不但速度慢,而且会产生一个undo的bug,考虑到使用分区表来解决此问题,也就是按照每个月划分range 分区,删除上一个月的数据的时候直接truncate partition 。我们使用dbms_redefinition包来完成表的在线分区功能。
创建一个在线表:
1、选择重新定义的方法。
一种为by key,也就是一个primary key 和psseudo-primary key,sseudo-primary is not null constraints, For this method, the versions of the tables before and after redefinition should have the same primary key columns,如果不指定options_flag则表示 使用默认该方法。
第二种是by rowid,添加了一个M_ROW$$的隐藏列,10.2.0之后,完了之后自动设置该column为unused,并且可以使用alter table ....drop unused column 去删除它。
2、使用can_redef_table确认一下该表是否可以在线重定义,如果不行的话那么就会报错
3、创建一个过渡表(在同一个schema下)包含所需的物理结构和逻辑属性。不是必须要创建该表的索引啊、约束啊、触发器啊等等。因为在使用copy_table_dependents的时候会自动创建。
4、如果使用by rowid,那么需要启动表的movement,alter table 。。。。。enable row movement;
5、为了加快处理大表的速度,可以使用并行操作。alter session force parallel dml paralle number; alter session force parallel query parallel number;
6、开始重新定义进程start_redef_table,指定schema和表名,指定过渡表,指定重定义的方法(dbms_redefinition.cons_use_pk or dbms_redefinition.cons_use_rowid)。
note:
You can query the DBA_REDEFINITION_OBJECTS view to list the objects currently involved in online redefinition.
 
If START_REDEF_TABLE fails for any reason, you must call ABORT_REDEF_TABLE, otherwise subsequent attempts to redefine the table will fail.
7、复制dependent 对象(如索引、触发器、物理话视图日志、授权、约束)和统计信息从需要新定义的表到过渡表中。有两种办法、1中是首选的也就是自动。2中是需要手动操作
对于第一种,我们使用dbms_redefinition.copy_table_dependents过程来在内部表中自动创建依赖的对象。但这会使该过渡表的dependent的名字和original dependent objects的名字一样。
第二种,就是手动进行操作了。注意要在执行完操作后必须是使用register_dependent_object 过程来重新注册这些依赖的对象。
8、执行finish_table完成表的重定义操作。
9、如果使用by rowid那么要删除伪列。在10.2.0之前会产生M_row$$一个标示列,需要设置unused然后删除,在10.2.0之后该M_ROW$$会自动设置为unused,可以执行alter table drop unused columns;
10、等待一段时间,保证所有的查询都在临时表中,那么接着删除该过渡表,有可能出现ORA-08103的错误。(谨记)
 
目前我有张表为amy。共有100多万条数据。如下:
SQL> conn rhys/amy;
Connected.

SQL> select count(*) from amy;

  COUNT(*)
----------
   1032509

SQL>

SQL> desc amy;
 Name                          Null?    Type
 ----------------------------- -------- --------------------
 ID                                     NUMBER
 CREATE_DATE                            TIMESTAMP(6)

SQL> 
查看该表 是否可以进行在线重定义。
SQL> execute dbms_redefinition.can_redef_table('RHYS','AMY',dbms_redefinition.cons_use_rowid);

PL/SQL procedure successfully completed.

SQL> alter table amy add constraint primary_key_id primary key (id);

Table altered.

SQL>

创建过渡表:
SQL> get bb.sql
  1  create table amy_temp(
  2  id number,
  3  create_date timestamp
  4  )
  5  partition by range(id)
  6  (
  7  partition part200000 values less than (200000),
  8  partition part500000 values less than (500000),
  9  partition part_other values less than (maxvalue)
 10* )
SQL> r
  1  create table amy_temp(
  2  id number,
  3  create_date timestamp
  4  )
  5  partition by range(id)
  6  (
  7  partition part200000 values less than (200000),
  8  partition part500000 values less than (500000),
  9  partition part_other values less than (maxvalue)
 10* )

Table created.

SQL> 
为了加快速度,设置并行操作;
SQL> 
SQL> alter session force parallel dml parallel 4;

Session altered.

SQL> alter session force parallel query parallel 4;

Session altered.

SQL> 
开始 执行重定向操作:
SQL> begin  
  2  dbms_redefinition.start_redef_table(
  3  uname=>'RHYS',
  4  ORIG_TABLE=>'AMY',
  5  INT_TABLE=>'AMY_TEMP',
  6  OPTIONS_FLAG=>(DBMS_REDEFINITION.CONS_USE_ROWID)
  7  );
  8  end ;
  9  /

PL/SQL procedure successfully completed.

SQL> select * from dba_redefinition_objects;
OBJECT_TYPE  OBJECT_OWNER         OBJECT_NAME                    BASE_TABLE_OWNER               BASE_TABLE_NAME                INTERIM_OBJECT_OWNER INTERIM_OBJECT_NAME
------------ -------------------- ------------------------------ ------------------------------ ------------------------------ -------------------- ------------------------------
EDITION_NAME
------------------------------
TABLE        RHYS                 AMY                            RHYS                           AMY                            RHYS                 AMY_TEMP

执行完后,查看相关信息:
SQL> 
SQL> select count(*) from amy_temp;

  COUNT(*)
----------
   1032509

SQL> select count(*) from amy;

  COUNT(*)
----------
   1032509

SQL> select PARTITIONED  from user_tables where table_name='AMY';

PAR
---
NO

SQL> SELECT PARTITIONED FROM USER_TABLES WHERE TABLE_NAME='AMY_TEMP';

PAR
---
YES

SQL> SELECT OWNER,CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME='AMY';

OWNER                          CONSTRAINT_NAME                C TABLE_NAME
------------------------------ ------------------------------ - ------------------------------
RHYS                           PRIMARY_KEY_ID                 P AMY

SQL> SELECT OWNER,CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME FROM USER_CONSTRAINTS WHERE TABLE_NAME='AMY_TEMP';

no rows selected

SQL>                                      
SQL> select table_name,column_name,data_type from user_tab_cols where table_name='AMY';

TABLE_NAME                     COLUMN_NAME                    DATA_TYPE
------------------------------ ------------------------------ ----------------------------------------------------------------------------------------------------------
AMY                            ID                             NUMBER
AMY                            CREATE_DATE                    TIMESTAMP(6)

SQL> COL TABLE_NAME FOR A50
SQL> COL DATA_TYPE FOR A60
SQL> R
  1* select table_name,column_name,data_type from user_tab_cols where table_name='AMY'

TABLE_NAME                                         COLUMN_NAME                    DATA_TYPE
-------------------------------------------------- ------------------------------ ------------------------------------------------------------
AMY                                                ID                             NUMBER
AMY                                                CREATE_DATE                    TIMESTAMP(6)

SQL> C /AMY/AMY_TEMP
  1* select table_name,column_name,data_type from user_tab_cols where table_name='AMY_TEMP'
SQL> R
  1* select table_name,column_name,data_type from user_tab_cols where table_name='AMY_TEMP'

TABLE_NAME                                         COLUMN_NAME                    DATA_TYPE
-------------------------------------------------- ------------------------------ ------------------------------------------------------------
AMY_TEMP                                           ID                             NUMBER
AMY_TEMP                                           CREATE_DATE                    TIMESTAMP(6)
AMY_TEMP                                           M_ROW$$                        VARCHAR2

SQL>

SQL> SELECT * FROM USER_CONS_COLUMNS WHERE TABLE_NAME='AM
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,