Tables can be reorganized and redefined (evolved) on-line with the DBMS_REDEFINITION package. The process is similar to on-line rebuilds of indexes, in that the original table is left on-line, while a new copy of the table is built. However, an index index-rebuild is a singular operation, while table redefinition is a multi-step process.
Table redefinition is started by the DBA creating an interim table based on the original table. The interim table can have a different structure than the original table, and will eventually take the original table's place in the database. While the table is redefined, DML operations on the original table are captured in a Materialized View Log table (MLOG$_%). These changes are eventually transformed and merged into the interim table. When done, the names of the original and the interim tables are swapped in the data dictionary. At this point all users will be working on the new table and the old table can be dropped.
Possible applications:
On-line Table Redefinition can be used for:
Restrictions:
Using On-line Redefinition from Enterprise Manager:
Oracle Enterprise Manager's REORG Wizard (part of the Tuning pack) allows DBAs to reorganize tables off-line or on-line. If on-line reorganization is chosen, Oracle will make use of the DBMS_REDEFINITION package. Off-line reorganization is quicker than on-line reorganization, but if the system cannot go down, the on-line method will prove valuable.
Execute the following steps to start the REORG Wizard: Start OEM. Click on TOOLS -> TUNING PACK -> REORG WIZARD.
Using On-line Redefinition from SQL*Plus:
A table can be redefined in 7 easy steps from SQL*Plus.
Step 1: Grant privileges:
Grant EXECUTE ON DBMS_REDEFINITION and the following privileges to the user that will do the redefinition: CREATE ANY TABLE, ALTER ANY TABLE, DROP ANY TABLE, LOCK ANY TABLE, SELECT ANY TABLE. Look at this example:
SQL> grant execute on dbms_redefinition to scott; SQL> grant dba to scott;
Note: These are powerful privileges, so remember to revoke them afterwards.
Step 2: Test if the table can be redefined:
Execute the DBMS_REDEFINITION.CAN_REDEF_TABLE procedure to test if a table can be redefined or not. A table qualifies for redefinition if no exceptions are raised. Possible errors:
SQL> EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('scott', 'emp', DBMS_REDEFINITION.CONS_USE_PK);
Note: The redefinition process can be based on a Primary Key or ROWID. Two constants are defined for this purpose: DBMS_REDEFINITION.CONS_USE_PK (the default) and DBMS_REDEFINITION.CONS_USE_ROWID. One can also use the value "1" for the primary key method, and "2" to indicate the rowid method. This is required so Oracle will know how to create the mview log: WITH ROWID, or WITH PRIMARY KEY.
Step 3: Create an interim table with new structure
Create an interim table with the new table structure. Define a primary key if you want to use the primary key method (DBMS_REDEFINITION.CONS_USE_PK). This is not required for the rowid method.
Oracle will TRUNCATE the interim table in step 4; so, do not add any data to it yet. Avoid adding constraints and indexes at this stage (for best performance).
Step 4: Start the redefinition
During this phase Oracle will copy (and transform) the data from the production table to the interim table. Oracle will also create a materialized view (snapshot) log on the table to track DML changes.
SQL> exec dbms_redefinition.start_redef_table('scott', 'emp', 'emp_work', - > 'emp_id emp_id, ename ename, salary salary', - > DBMS_REDEFINITION.CONS_USE_PK);
Note parameter 4: mapping for the old table's columns to the new table's columns. This can be left out if the columns are the same.
Step 5: Sync intermediate changes to interim table (optional)
This step will apply changes captured in the materialized view log to the interim table. Perform this step frequently for high transaction tables.
SQL> exec dbms_redefinition.sync_interim_table('scott', 'emp', 'emp_work');
Step 6: Create indexes, constraints and triggers on the interim table
Note that you cannot use the same names for indexes and constraints. Foreign key constraints must be created DISABLED (Oracle will enable them in step 6).
Step 7: Complete the redefinition process
During this step Oracle will lock both tables in exclusive mode, swap the names of the two tables in the data dictionary, and enable all foreign key constraints. Remember to drop the original table afterwards. One can also consider renaming the constraints back to their original names (e.g.: alter table EMP rename constraint SYS_C001806 to emp_fk).
SQL> exec dbms_redefinition.finish_redef_table('scott', 'emp', 'emp_work');
Optional step to Abort Redefinition:
Redefinition can be aborted at any stage by calling the DBMS_REDEFINITION.ABORT_REDEF_TABLE procedure. This will drop the mview log on the production table. Note that you need to abort before trying again, otherwise you will get an ORA-12091 error as described in step 2.
Examples:
Example 1: On-line Table Reorg using the rowid method
EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('scott', 'emp', 2); -- 2=rowid CREATE TABLE emp_work AS SELECT * FROM emp WHERE 1=2; EXEC DBMS_REDEFINITION.START_REDEF_TABLE('scott', 'emp', 'emp_work', NULL, 2); ALTER TABLE emp ADD PRIMARY KEY (empno); EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('scott', 'emp', 'emp_work'); DROP TABLE emp_work;
Example 2: Redefine a table using the primary key method
-- Create a new table with primary key... CREATE TABLE myemp ( empid NUMBER PRIMARY KEY, ename VARCHAR2(30), salary NUMBER(8,2), deptno NUMBER); insert into myemp values (1, 'Frank', 15000, 10); insert into myemp values (2, 'Willie', 10000, 20); create index myemp_idx on myemp (ename); -- Test if redefinition is possible... EXEC DBMS_REDEFINITION.CAN_REDEF_TABLE('scott', 'myemp'); -- Create new empty interim table... CREATE TABLE myemp_work ( emp# NUMBER PRIMARY KEY, -- Change emp_id to emp# ename VARCHAR2(30), salary NUMBER(8,2), -- We will increase salary by 10% deptno NUMBER) PARTITION BY LIST (deptno) ( -- Add list partitioning PARTITION p10 VALUES (10), PARTITION p20 VALUES (20), PARTITION p30 VALUES (30,40)); -- Create a transformation function... CREATE FUNCTION raise_sal (salary NUMBER) RETURN NUMBER AS BEGIN return salary + salary*0.10; END; / -- Start the redefinition process EXEC DBMS_REDEFINITION.START_REDEF_TABLE('scott', 'myemp', 'myemp_work', - 'empid emp#, ename ename, raise_sal(salary) salary, deptno deptno', - DBMS_REDEFINITION.CONS_USE_PK); -- Apply captured changed to interim table EXEC DBMS_REDEFINITION.SYNC_INTERIM_TABLE('scott', 'myemp', 'myemp_work'); -- Add constraints, indexes, triggers, grants on interim table... create index myempidx2 on myemp_work (ename); -- Finish the redefinition process... EXEC DBMS_REDEFINITION.FINISH_REDEF_TABLE('scott', 'myemp', 'myemp_work'); -- Cleanup DROP TABLE myemp_work; DROP FUNCTION raise_sal;