Oracle数据库提供了一种机制,可以在不明显影响表的可用性情况下进行表结构更改。当表在线重定义时,在重定义过程中,可以对表进行查询或DML。该表仅在非常小的窗口期以独占模式被锁定,该窗口独立于表格的大小和重定义的复杂性,并且对用户完全透明。在线重定义表需要大量的空闲空间,大致为被重定义表的二倍空间,如果添加新列则需要更多的空间。
在线重定义表能够实现以下效果:
- 修改表或集群的存储参数
- 将表或群集移动到不同的表空间
- 在表或群集中添加,修改或删除一列或多列
- 添加或删除分区支持(仅限非Cluster表)
- 更改分区结构
- 更改单个表分区的物理属性,包括将其移动到同一模式中的其他表空间
- 更改物化视图日志或Oracle Streams高级队列队列表的物理属性
- 添加对并行查询的支持
- 重新创建表或群集以减少碎片
- 将普通表(堆组织)更改为索引组织表,或者相反
- 将关系表转换为包含对象列的表格,或者做相反的操作
- 将对象表转换为关系表或具有对象列的表,或者相反
先决条件
除去包的执行权限,还需要用到如下权限:
- DBMS_REDEFINITIONEXECUTE_CATALOG_ROLE
- CREATE ANY TABLE
- ALTER ANY TABLE
- DROP ANY TABLE
- LOCK ANY TABLE
- SELECT ANY TABLE
- CREATE ANY TRIGGER
- CREATE ANY INDEX
重定义步骤
- 选择重定义的方法 Key:选择用于重新定义的主键或伪主键。伪主键是唯一键。所有组件列都有非空约束。对于此方法,重定义前后的表版本应具有相同的主键列。这是重新定义的首选和默认的方法 ROWID:如果没有key可用,请使用此方法。在这种方法中,将一个隐藏的列名M_ROW$$添加到重定义后的表。建议在重定义完成后删除该列或将其标记为未使用。如果COMPATIBLE设置为10.2或更高,在重定义最后阶段会自动设置该列未使用。可以通过ALTER TABLE …. DROP UNUSED COLUMNS删除
- 通过调用CAN_REDEF_TABLE过程验证是否可以在线重定义该表
- 创建一个空的临时表(同一schema下),如果要删除列,则不要包含在临时表中;如果要增加列,请将列定义添加到临时表中;如果要修改列,请在临时表中设置
- (可选)如果表比较大,可以通过并行来提高性能。 alter session force parallel dml parallel degree-of-parallelism; alter session force parallel query parallel degree-of-parallelism;
- 调用过程START_REDEF_TABLE启动重定义,并提供如下信息:
- 要重定义的表的用户名和表名
- 临时表名称
- 列映射
- 重定义方法。DBMS_REDEFINITION.CONS_USE_PK用于指示应使用主键或伪主键完成重定义。DBMS_REDEFINITION.CONS_USE_ROWID用于指示应使用rowid完成重定义
- (可选)用于排序行的列
- 如果仅重新定义分区表的单个分区,则设置分区名称
- 选择下列两种方法之一,将被重定义的表的相关对象统计信息复制到临时表中 自动创建相关对象:使用COPY_TABLE_DEPENDENTS过程可以在临时表上自动创建相关对象。此过程还会注册依赖对象 手动创建相关对象:手动在临时表上创建相关对象,然后注册它们
- 执行FINISH_REDEF_TABLE过程完成表的重定义
- 等待重定义结束,删除临时表
示例
hr.admin_emp表包含empno,ename,job,deptno列,现在要求重定义规则如下:
- 增加mgr,hiredate,sal,bonus列
- 新列bonus初始化为0
- deptno列的值增加10
- 重定义表对列empno进行范围分区
验证表是否可以在线重定义
|
|
创建临时表
|
|
开始重定义
|
|
复制相关对象
|
|
ignore_errors参数设置为TRUE是因为临时表是用主键约束创建的。当COPY_TABLE_DEPENDENT尝试从原始表中复制主键约束和索引时,会发生错误。您可以忽略这些错误,但必须运行下一步中显示的查询以查看是否存在其他错误。
检查错误
|
|
同步临时表(可选)
|
|
完成重定义
|
|
待重定义完成,删除临时表
更多在线重定义信息请查阅Redefining Tables Online