Add / drop columns in compressed table

The question come from Ask Tom:

Would it be possible to add or remove the columns from a Compressed table?

Below is the answer and sample:

ops$tkyte%ORA10GR2> create table test_compress compress as select * from dba_users;

Table created.

ops$tkyte%ORA10GR2> alter table add obsolete_clom number;

Table altered.


physically drop, no:

ops$tkyte%ORA10GR2> alter table  test_compress   drop column obsolete_clom ;
alter table  test_compress   drop column obsolete_clom 
                          *
ERROR at line 1:
ORA-39726: unsupported add/drop column operation on compressed tables

but make it "disappear"
ops$tkyte%ORA10GR2> alter table test_compress set unuesd column obsolete_clom

Table altered.

yes, which if you ask me is OK since you would have to rewrite the entire segment to
truly get rid of the data anyway (and recompress it).  So follow that with:


ops$tkyte%ORA10GR2> alter table test_compress drop unused columns;

Table altered.

and it is gone

Collect tech guidance  for using set unused:

we can get unused column info from below system dict;

select * from dba_unused_col_tabs;

SET UNUSED的用法


原理:清楚掉字典信息(撤消存储空间),不可恢复。

   可以使用 SET UNUSED 选项标记一列或者多列不可用。

   使用DROP SET UNUSED 选项删除被被标记为不可用的列。

语法:

   ALTER TABLE table SET UNUSED (COLlist多个) 或者 ALTER TABLE table SET UNUSED COLUMN col单个;

   ALTER TABLE table DROP UNUSED COLUMNS;


set unused不会真地删除字段。
除了alter table drop field外,也可以
alter table set   unused field;
alter table drop unused;
set unused系统开销比较小,速度较快,所以可以先set unuased,然后在系统负载较小时,再drop。如系统负载不大,也可以直接drop。
不管用何种方法,都不会收回空间。


如果你有这个需求,要删除某一个表格上的某些栏位,但是由於这个表格拥有非常大量的资料,如果你在尖峰时间直接执行 ALTER TABLE ABC DROP (COLUMN);可能会收到 ORA-01562 - failed to extend rollback segment number string,
这是因为在这个删除栏位的过程中你可能会消耗光整个RBS,造成这样的错误出现,因此这样的做法并不是一个好方法,就算你拼命的加大RBS空间来应付这个问题,也不会是个好主意。

        我的建议做法:

        1>

        CREATE TABLE T1 (A NUMBER,B NUMBER);

        SQL> begin 2 for i in 1 …… 100000 3 loop 4 insert into t1 values (i,100);5 end loop;6 commit;7 end;

        SQL> select count(*) from t1;

        COUNT(*)

        100000

        2>

        SQL> ALTER TABLE T1 SET UNUSED COLUMN A CASCADE CONSTRAINTS;

        不要马上drop column,应该先set unused让column无法使用,避开系统尖峰时间再来处理删除栏位里的资料,要注意的是一但你set unused column,这个栏位是无法再回复使用的。

        3>

        重点来了,若你的栏位有一百万笔资料,我们应该避免一次写入那么多的undo log,所以我准备每删除一千笔资料就commit一次。

        SQL> alter table t1 drop unused columns checkpoint 1000;

        Table altered.

        在离峰的时间进行这样的动作,应该可以避免 ORA-01562 的错误发生。


刚才有个人问我如何修复被设置为UNUSED的字段,我考虑了一下,以下的方法可以恢复(以下步骤执行前要做好备份),没有经验的DBA不要轻易尝试。

1、创建实验表TTTA

SQL> CREATE TABLE TTTA ( A INTEGER,B INTEGER,C VARCHAR2(10),D INTEGER);

表已创建。

SQL> INSERT INTO TTTA VALUES (1,2,'3',4);

已创建 1 行。

SQL> INSERT INTO TTTA VALUES (2,3,'4',5);

已创建 1 行。

SQL> COMMIT;

提交完成。
ALTER TABLE TTTA SET UNUSED COLUMN C;

2、以下进行恢复

SQL> SELECT OBJ# FROM OBJ$ WHERE NAME='TTTA';

      OBJ#
----------
     32067

SELECT COL#,INTCOL#,NAME FROM COL$ WHERE OBJ#=32067;
      COL#    INTCOL# NAME
---------- ---------- ------------------------------
         1          1 A
         2          2 B
         0          3 SYS_C00003_08031720:09:55$   被UNUSED的字段
         3          4 D

SQL> SELECT COLS FROM TAB$ WHERE OBJ#=32067;

      COLS
----------
         3      ------字段数变为3了

 


SQL> UPDATE COL$ SET COL#=INTCOL# WHERE OBJ#=32067;

已更新4行。

SQL> UPDATE TAB$ SET COLS=COLS+1 WHERE OBJ#=32067;

已更新 1 行。

UPDATE COL$ SET NAME='C' WHERE OBJ#=32067 AND COL#=3;

UPDATE COL$ SET PROPERTY=0 WHERE OBJ#=32067;
SQL> COMMIT;

3、重启数据库
SQL> SELECT * FROM SCOTT.TTTA;

         A          B C                   D
---------- ---------- ---------- ----------
         1          2 3                   4
         2          3 4                   5

恢复完成

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/781883/viewspace-664842/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/781883/viewspace-664842/

你可能感兴趣的:(Add / drop columns in compressed table)