【问题标题】:Can I partition an already existing table in oracle?我可以在 oracle 中对已经存在的表进行分区吗?
【发布时间】:2016-02-22 22:29:50
【问题描述】:

我的 oradb 中有一个表,它已经有很多行了。

我想通过不重新创建来按月对这个表进行分区。所以我不想丢失表中的数据。

我想要这种分区类型:

PARTITION BY RANGE (date_column)
INTERVAL (NUMTOYMINTERVAL (1,'MONTH')) 
         (partition transaction_old values less than (to_date('01-01-2015','DD-MM-YYYY')));

如何将其设置为已经存在的表?我想使用 alter table 功能,但它不起作用:

alter table mytable
    PARTITION BY RANGE (date_column)
    INTERVAL (NUMTOYMINTERVAL (1,'MONTH')) 
             ( partition transaction_old values less than (to_date('01-01-2015','DD-MM-YYYY') ));

我的问题有什么解决办法吗?

【问题讨论】:

  • dbms_redefinition 包。检查答案here
  • 只有一个警告,您可能需要 dba privs 才能执行 dbms_redefinition。当您无法使用它时(即使在您自己的表上),您只是拥有连接、资源权限的数据库用户。

标签: oracle database-partitioning partition


【解决方案1】:

可能最简单、最安全的方法是使用 dbms_redefinition - 它会复制授权、索引、约束等所有内容。

Table P is the parent table. 

Table T1 is the existing non-partitioned table. 
Table T2 is the new partitioned table. 

At the end, we are left with P and T1 - T1 being partitioned. 


ops$tkyte%ORA10GR2> create table p ( x primary key )
  2  as
  3  select user_id from all_users;

Table created.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create table t1
  2  as
  3  select * from all_users
  4  /

Table created.

ops$tkyte%ORA10GR2> alter table t1 add constraint t1_pk primary key(user_id);

Table altered.

ops$tkyte%ORA10GR2> alter table t1 add constraint t1_fk foreign key(user_id) references 
p(x);

Table altered.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> create table t2
  2  ( username varchar2(30),
  3    user_id  number,
  4    created  date
  5  )
  6  partition by hash(user_id) partitions 8;

Table created.

ops$tkyte%ORA10GR2> exec dbms_redefinition.can_redef_table( user, 'T1' );

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> exec dbms_redefinition.start_redef_table( user, 'T1', 'T2' );

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> variable nerrors number
ops$tkyte%ORA10GR2> begin
  2          dbms_redefinition.copy_table_dependents
  3          ( user, 'T1', 'T2',
  4            copy_indexes => dbms_redefinition.cons_orig_params,
  5            num_errors => :nerrors );
  6  end;
  7  /

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2> exec dbms_redefinition.finish_redef_table( user, 'T1', 'T2' );

PL/SQL procedure successfully completed.

ops$tkyte%ORA10GR2>
ops$tkyte%ORA10GR2> select dbms_metadata.get_ddl( 'TABLE', 'T1' ) from dual;

DBMS_METADATA.GET_DDL('TABLE','T1')
-------------------------------------------------------------------------------

  CREATE TABLE "OPS$TKYTE"."T1"
   (    "USERNAME" VARCHAR2(30) CONSTRAINT "SYS_C0026838" NOT NULL ENABLE NOVALIDA
TE,
        "USER_ID" NUMBER CONSTRAINT "SYS_C0026839" NOT NULL ENABLE NOVALIDATE,
        "CREATED" DATE CONSTRAINT "SYS_C0026840" NOT NULL ENABLE NOVALIDATE,
         CONSTRAINT "T1_PK" PRIMARY KEY ("USER_ID")
  USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS
  STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
  PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
  TABLESPACE "USERS"  ENABLE NOVALIDATE,
         CONSTRAINT "T1_FK" FOREIGN KEY ("USER_ID")
          REFERENCES "OPS$TKYTE"."P" ("X") ENABLE NOVALIDATE
   ) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255
  STORAGE(
  BUFFER_POOL DEFAULT)
  TABLESPACE "USERS"
  PARTITION BY HASH ("USER_ID")
 (PARTITION "SYS_P1017"
   TABLESPACE "USERS",
 PARTITION "SYS_P1018"
   TABLESPACE "USERS",
 PARTITION "SYS_P1019"
   TABLESPACE "USERS",
 PARTITION "SYS_P1020"
   TABLESPACE "USERS",
 PARTITION "SYS_P1021"
   TABLESPACE "USERS",
 PARTITION "SYS_P1022"
   TABLESPACE "USERS",
 PARTITION "SYS_P1023"
   TABLESPACE "USERS",
 PARTITION "SYS_P1024"
   TABLESPACE "USERS")



ops$tkyte%ORA10GR2> select constraint_name, constraint_type from user_constraints where 
table_name = 'T1';

CONSTRAINT_NAME                C
------------------------------ -
SYS_C0026838                   C
SYS_C0026839                   C
SYS_C0026840                   C
T1_PK                          P
T1_FK                          R

Source

【讨论】:

    【解决方案2】:

    您不能直接分区现有的非分区表。您将需要根据以下分区方法创建临时表/新表:

    • DBMS_REDEFINITION

      1. 创建分区临时表
      2. 开始重新定义过程
      3. 创建约束和索引(依赖)
      4. 完成重新定义过程
    • EXCHANGE PARTITION

      1. 创建分区目标表
      2. 交换分区
      3. SPLIT PARTITION(如果需要将单个大分区拆分为较小的分区)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-10-17
      • 1970-01-01
      • 2015-09-02
      • 1970-01-01
      • 2016-11-26
      • 2019-10-09
      • 1970-01-01
      • 2011-05-12
      相关资源
      最近更新 更多