【IT168 服务器学院】 方法二:改进了的传统清除行迁移的方法
1. 执行$ORACLE_HOME/rdbms/admin目录下的utlchain.sql脚本创建chained_rows表。
2. 禁用所有其它表上关联到此表上的所有限制。
3. 将表中的行迁移的row id放入临时表中保存。
4. 删除原来表中存在的行迁移的记录行。
5. 从临时表中取出并重新插入那些被删除了的数据到原来的表中,并删除临时表。
6. 启用所有其它表上关联到此表上的所有限制。
这种算法是对传统算法的一种改进,对于使用这种算法来清除行迁移,考虑到了表之间的关联,还可以灵活的利用的TOAD工具生成的表关联信息,是一种比较适合于清除行迁移的一种方法。但是因为使用这种方法后来需要重建索引,如果记录数很大,比如说上千万条以上的记录的表,就不是很合适了,因为这个重建索引的时间会很长,是线性时间复杂度的,而重建索引是会导致索引所在的表被锁定的,从而导致插入不了新的记录,重建索引的时间太长导致记录长时间插入不了是会严重影响应用的,甚至导致数据的丢失,因此这个是使用这个方法前必须要考虑到的一个重要因素;对于8i以上的版本可以使用online的方法来重建索引,这样不会导致锁表,但是会有额外更多的开销,时间会很长。再者,因为这种方法在插入记录和删除记录都是带着索引的,如果表上的行迁移比较多,这样耗时间会比较长,而且占用资源也会比较大,因此只适用于表上行迁移存在的比较少的表。总的来说,这种方法对于表记录太多或者是表上的行迁移太多的情况都不是很适用,比较适合表记录少和表上行迁移都不太多的情况。
以下是一个具体在生产数据库上清除行迁移的例子,在这之前已经调整过表的pctfree参数至一个合适的值了:
SQL>select index_name,index_type,table_name from user_indexes where table_name=''TERMINAL'';
INDEX_NAME INDEX_TYPE TABLE_NAME
-----------------------------------------------------------------
INDEX_TERMINAL_TERMINALCODE NORMAL TERMINAL
I_TERMINAL_ID_TYPE NORMAL TERMINAL
I_TERMINAL_OT_OID NORMAL TERMINAL
PK_TERMINAL_ID NORMAL TERMINAL
UI_TERMINAL_GOODIS_SSN NORMAL TERMINAL
SQL>select CONSTRAINT_NAME,CONSTRAINT_TYPE,TABLE_NAME from USER_CONSTRAINTS where R_CONSTRAINT_NAME=''PK_TERMINAL_ID'';
CONSTRAINT_NAME C TABLE_NAME
------------------------------ - ------------------------------
SYS_C003200 R CONN
SQL>alter table CONN disable constraint SYS_C003200;
Table altered.
SQL>CREATE TABLE TERMINAL_temp AS
SELECT * FROM TERMINAL
WHERE rowid IN
(SELECT head_rowid FROM chained_rows
WHERE table_name = ''TERMINAL'');
Table created.
SQL>select count(*) from TERMINAL_temp;
COUNT(*)
----------
8302
SQL>DELETE TERMINAL
WHERE rowid IN
(SELECT head_rowid
FROM chained_rows
WHERE table_name = ''TERMINAL'');
8302 rows deleted.
SQL>INSERT INTO TERMINAL SELECT * FROM TERMINAL_temp;
8302 rows created.
SQL>alter table CONN disable constraint SYS_C003200;
Table altered.
SQL>select count(*) from terminal;
COUNT(*)
----------
647799
SQL>truncate table chained_rows;
Table truncated.
SQL>ANALYZE TABLE TERMINAL LIST CHAINED ROWS INTO chained_rows;
Table analyzed.
SQL>select count(*) from chained_rows;
COUNT(*)
----------
0
从上面过程中可以看出,对TERMINAL这张表的行迁移清除耗时总共不到五分钟的时间,总体来说还是比较快的。从我在生产数据库中清除行迁移的经验来说,这种方法基本适用于大部分存在有行迁移的表。
Oracle数据库中行迁移/行链接的问题之二
0
相关文章