本文档 ID 1985005.1
如何将oralce普通表转换为分区表,此前面试被问到过,虽然知道在线重定义,个人觉得很简单,查查文档做个试验就差不多了,但自己没亲自操作过有点心虚;这次抽点时间好好研究一下!
可以任选如下四种方法的一种来对非分区表进行分区:
A) 通过 expdp/impdp 方法
B) 通过 Insert with a subquery 方法
C) 通过 Partition Exchange 方法
D) 通过 DBMS_REDEFINITION,(在线重定义)法
以上四种方法都会从一个已经存在的非分区表创建出一个分区表。管我们已经对这四种方法的维护时间预期做了倒序排列,但实际维护时间针对不同情况有所不同。
方法一:通过 expdp/impdp 方法
1) expdp非分区表:
[oracle@node3 node3]$ expdp scott/tiger tables=numbers dumpfile=number.dmp
2) Drop 掉该非分区表:
SQL> drop table numbers;
3) 重新创建该表成为一个分区表:
create table numbers (
qty number(3),
name varchar2(15)
)
partition by range (qty)(
partition p1 values less than (200),
partition p2 values less than (400),
partition p3 values less than (600),
partition p4 values less than (maxvalue) ) ;
4) 通过 impdp 的 table_exists_action 方式来还原备份的数据:
[oracle@node3 node3]$ impdp scott/tiger file=number.dmp table_exists_action=append
而使用impdp完成数据库导入时,若表已经存在,有四种的处理方式:
1) skip :默认操作,如果表存在,则跳过
2) replace :先drop表,然后创建表,最后插入数据
3) append :在原来数据的基础上增加数据
4) truncate:先truncate,然后再插入数据
方法二: Insert with a subquery
1 ) 创建一个分区表:
create table numbers_part (
qty number(3),
name varchar2(15)
)
partition by range (qty)(
partition p1 values less than (200),
partition p2 values less than (400),
partition p3 values less than (600),
partition p4 values less than (maxvalue) ) ;
2) 将原来非分区表中的数据通过子查询 i nsert 到新创建的分区表中:
SQL> insert into numbers_part (qty, name) select * from numbers;
3) 如果您想让新建的分区表与原表名相同,那么drop 掉原来的非分区表然后重命名新表:
SQL> drop table numbers;
SQL> alter table numbers_part rename to numbers;
您可以通过 direct path insert 和利用并行来改善 insert 的性能。
create as 方式
另外一种可选的方式是直接通过select来创建新的分区表:一次性创建新的分区表并且加载数据。
执行计划同时显示 direct pathload 并且 dml 以及 select 部分全部并行。
SQL>alter session enable parallel dml;
SQL>create table numbers_part (qty,name)
partition by range (qty)(
partition p1 values less than (200),
partition p2 values less than (400),
partition p3 values less than (600),
partition p4 values less than (maxvalue)
)
as select /*+parallel*/ * from numbers;
方法三: 通 过 Partition Exchange 方 法
alter table exchange partition 可以通过交换数据和索引segment来将一个分区(或子分区) 转换成一个非分区表,
也可以将一个非分区表转换成一个分区表的分区(或子分区) 。除了需要更新索引以外, alter table . . . exchange partition
命令是一个字典操作不需要数据移动。 更多关于此方法的信息参见 Oracle联机文档(比如 11.2) 和 Note 198120.1 。
此方法简要步骤如下:
1)根据所需的分区来创建新的分区表
2) 保持需要交换的非分区表与分区表的分区有相同的结构,并且确保您需要交换的非分区表具有您想要交换的内容
3) 执行: Alter table exchange partiti on partiti on_name with table exchange table
注意在交换过程中,所有交换的数据必须满足分区表的分区定义, 否则如下错误将抛出:
ORA-14099: all rows in table do not qualify for specified partition.
这是因为默认情况下分区交换是有校验的。
例子( 基于 SCOTT 示例 schema)
本例创建了 与分区表 p_emp 的分区相同结构的交换表。
create table p_emp(
sal number(7, 2)
)
PARTITION BY RANGE(sal)
(partition emp_p1 VALUES LESS THAN (2000),
partition emp_p2 VALUES LESS THAN (4000)
) ;
SQL> SELECT * FROM emp;
7369 SMITH CLERK 7902 1980/12/17 800.00 20
7499 ALLEN SALESMAN 7698 1981/2/20 1600.00 300.00 30
7521 WARD SALESMAN 7698 1981/2/22 1250.00 500.00 30
7566 JONES MANAGER 7839 1981/4/2 2975.00 20
7654 MARTIN SALESMAN 7698 1981/9/28 1250.00 1400.00 30
7698 BLAKE MANAGER 7839 1981/5/1 2850.00 30
7782 CLARK MANAGER 7839 1981/6/9 2450.00 10
7788 SCOTT ANALYST 7566 1987/4/19 3000.00 20
7839 KING PRESIDENT 1981/11/17 5000.00 10
7844 TURNER SALESMAN 7698 1981/9/8 1500.00 0.00 30
7876 ADAMS CLERK 7788 1987/5/23 1100.00 20
7900 JAMES CLERK 7698 1981/12/3 950.00 30
7902 FORD ANALYST 7566 1981/12/3 3000.00 20
7934 MILLER CLERK 7782 1982/1/23 1300.00 10
SQL> create table exchtab1 as select sal from emp where sal<2000;
SQL> create table exchtab2 as select sal from emp where sal between 2000 and 3999;
SQL> alter table p_emp exchange partition emp_p1 with table exchtab1;
SQL> alter table p_emp exchange partition emp_p2 with table exchtab2;
方法四:dbms_redefinition 方 法(在线重定义)
Note 472449.1 How To Partiti on Existing Table Using DBMS_Redefiniti on
Note 1 481558.1 DBMS_REDEFINITI ON: Case Study for a Large Non-Parti ti on Table t
Parti ti on Tabl e wi th Onl i ne Transacti ons occuri ng
Note 1 77407.1 How to Re-Organi ze a Tabl e Online
How To Partition Existing Table Using DBMS_REDEFINITION (文档 ID 472449.1)
1.)创建一个表 numbers :
SQL>
create table numbers (
qty number(3),
name varchar2(15)
);
2) 给这个表添加一个主键,索引
SQL> alter table numbers add (constraints numbers_pk primary key (qty));
3) 收集信息
SQL> exec dbms_stats.gather_table_stats(USER, 'numbers', cascade => TRUE);
4)创建分区表
create table numbers_part
qty number(3),
name varchar2(15)
)
partition by range (qty)(
partition p1 values less than (200),
partition p2 values less than (400),
partition p3 values less than (600),
partition p4 values less than (maxvalue)) ;
5) 开始重定义
a. 使用以下命令检查表能否在线重定义
SQL> exec dbms_redefinition.can_redef_table(USER, 'numbers');
b.如果没有报告错误,使用下面的命令启动 redefintion
SQL> exec dbms_redefinition.start_redef_table( uname => USER, orig_table => 'numbers', int_table => 'numbers_part');
Note: 这个操作可能花费很长一段时间
c. 选择同步新表和临时名字创建索引:
SQL>exec dbms_redefinition.sync_interim_table( uname => USER, orig_table => 'numbers', int_table => 'numbers_part');
d. 创建约束和索引:
SQL> alter table numbers_part add ( constraints numbers_pk2qty) );
e. 收集新表的统计信息
SQL> exec dbms_stats.gather_table_stats(USER, 'numbers_part ', cascade => TRUE);
f. 重定义完成
SQL>exec dbms_redefinition.finish_redef_table( uname => USER, orig_table => 'numbers', int_table => 'numbers_part');
此时临时表已经变成 分区表它们的数据字典信息已经改变
g.删除临时表
SQL> drop table numbers_part;
h.重命名所有的约束和索引匹配原始的名字:
alter table numbers rename constraint numbers_pk2 to numbers_pk;
i. 我检查是否分区成功:
SQL> select partitioned from user_tables where table_name =upper('numbers');
PAR
---
YES
1 row selected.
SQL> select partition_name from user_tab_partitions where table_name =upper('numbers');
PARTITION_NAME
------------------------------
P1
P2
P3
P4
注意的问题
Restrictions for Online Redefinition of Tables in 9i
There must be enough space to hold two copies of the table.
需要足够的看空间存放两个表
Primary key columns cannot be modified.
主键列不能被修改
表必须有主键
Tables must have primary keys.
重定义必须在相同的用户下
Redefinition must be done within the same schema.
直到重新定义操作完成,添加新列不能使非空
New columns added cannot be made NOT NULL until after the redefinition operation.
表不能包含 LONGs, BFILEs 或用户定义的类型。
Tables cannot contain LONGs, BFILEs or User Defined Types.
簇表不能在线重定义
Clustered tables cannot be redefined.
sys用户或system用户下的表不能在线重定义
Tables in the SYS or SYSTEM schema cannot be redefined.
Tables with materialized view logs or materialized views defined on them cannot be redefined.
Horizontal sub setting of data cannot be performed during the redefinition.
Restrictions for Online Redefinition of Tables in 11.2
If the table is to be redefined using primary key or pseudo-primary keys (unique keys or constraints with all component columns having not null constraints), then the post-redefinition table must have the same primary key or pseudo-primary key columns. If the table is to be redefined using rowids, then the table must not be an index-organized table.
After redefining a table that has a materialized view log, the subsequent refresh of any dependent materialized view must be a complete refresh.
Tables that are replicated in an n-way master configuration can be redefined, but horizontal subsetting (subset of rows in the table), vertical subsetting (subset of columns in the table), and column transformations are not allowed.
The overflow table of an index-organized table cannot be redefined online independently.
Tables with fine-grained access control (row-level security) cannot be redefined online.
Tables for which Flashback Data Archive is enabled cannot be redefined online. You cannot enable Flashback Data Archive for the interim table.
Tables with BFILE columns cannot be redefined online.
Tables with LONG columns can be redefined online, but those columns must be converted to CLOBS. Also, LONG RAW columns must be converted toBLOBS. Tables with LOB columns are acceptable.
On a system with sufficient resources for parallel execution, and in the case where the interim table is not partitioned, redefinition of a LONG column to a LOB column can be executed in parallel, provided that:
The segment used to store the LOB column in the interim table belongs to a locally managed tablespace with Automatic Segment Space Management (ASSM) enabled.
There is a simple mapping from one LONG column to one LOB column, and the interim table has only oneLOBcolumn.
In the case where the interim table is partitioned, the normal methods for parallel execution for partitioning apply.
Tables in the SYS and SYSTEM schema cannot be redefined online.
Temporary tables cannot be redefined.
A subset of rows in the table cannot be redefined.
Only simple deterministic expressions, sequences, and SYSDATEcan be used when mapping the columns in the interim table to those of the original table. For example, subqueries are not allowed.
If new columns are being added as part of the redefinition and there are no column mappings for these columns, then they must not be declared NOTNULL until the redefinition is complete.
There cannot be any referential constraints between the table being redefined and the interim table.
Table redefinition cannot be done NOLOGGING.
For materialized view logs and queue tables, online redefinition is restricted to changes in physical properties. No horizontal or vertical subsetting is permitted, nor are any column transformations. The only valid value for the column mapping string isNULL.
You can convert a VARRAY to a nested table with the CAST operator in the column mapping. However, you cannot convert a nested table to a VARRAY.