oracle 大表在线删除列操作(alter table table_name set unused )

在某些情况下业务建的表某些列没有用到,需要进行删除,但是如果是数据量很大的大表,直接 alter table table_name drop column column_name;这种方法删除,那么将出现TM表锁,业务有可能hang住,所以不能这样子操作;Oracle 8i 引入了从表中删除列的能力。在此之前,有必要删除整个表并重建它。可以将列标记为未使用(逻辑删除)或完全删除(物理删除),下面介绍逻辑删除和物理删除。

一.逻辑删除

在大表上,物理删除列的过程非常耗时且耗费资源。决定从逻辑上删除最合适。实际上并未删除目标列数据或恢复这些列占用的磁盘空间。但是,标记为未使用的列不会显示在查询或数据字典视图中,并且会删除其名称,以便新列可以重用该名称。列上定义的所有约束、索引和统计信息也将被删除。

语法:

alter table table_name set unused (column_name) ONLINE; --加上ONLINE,业务不阻塞
alter table table_name set unused (column_name1, column_name2);

注意:set unused 语句是不可逆的操作,意思就是不能进行recover,除非你有备份。

完成此操作后,将不再看到这些列。如果以后您有时间物理删除列,可以使用以下方法完成。

alter table table_name drop unused columns ONLINE ;语句是对未使用的列唯一允许的操作。它从表中物理删除未使用的列并回收磁盘空间。
alter table table_name drop unused columns checkpoint XX;该子句导致在处理指定数量的行后应用检查点,在本例中为 1000。检查点减少了删除列操作期间累积的undo日志量,以避免undo空间的潜在耗尽。

DBA_UNUSED_COL_TABS 视图可用于查看每个表未使用的列数。

例如我需要删除user_order_detail 的DEL_IND,DEL_USER_ID,DEL_DTT这三列。

select count(*) from  user_order_detail ;

  

alter table user_order_detail set unused (DEL_IND,DEL_USER_ID,DEL_DTT); --这个执行是秒级别的非常快;建议删除后有触发器的涉及到这几列的重建触发器,oracle19-20c有bug,21c修复次BUG。

select * from DBA_UNUSED_COL_TABS;

 

alter table user_order_detail drop unused columns checkpoint 1000; --这个执行看你的数据量,物理删除比较慢。从表中物理删除未使用的列并回收磁盘空间。

 

 

 

 

 可以想象,才200多万数据删除3列这么久,如果不是采用set unused 这种方法删除,直接物理删除千万甚至亿级别的数据,业务响应将是多么的可怕。

 

二.物理删除

 要物理删除列,您可以使用以下语法之一,具体取决于您希望删除单个列还是多个列。

alter table table_name drop column column_name;
alter table table_name drop (column_name1, column_name2);
同时,从表中删除一列将导致该表中所有未使用的列同时被删除(即有set unused 的列将被删除)
大表一般不用这种方法删除,对业务影响太严重,小表就可以这么操作,在及时性要求不高的情况下。

 

最后

如果删除列之后,即:

alter table table_name set unused (column_name);有进行alter table table_name move;操作,至于move 和shrink操作的影响以及区别我在索引帖子里面已经说到过。


三.总结一下set unused

1.指定SET UNUSED将一列或多列标记为未使用。对于内部堆组织表,指定此子句实际上不会从表中的每一行中删除目标列。它不会恢复这些列使用的磁盘空间。因此,响应时间比执行DROP子句时要快

当您为外部表中的列指定此子句时,该子句将透明地转换为ALTER TABLE...DROP COLUMN语句。这样做的原因是,对外部表的任何操作都是元数据操作,因此两个命令的性能没有区别。

2.用标列的所有表UNUSED中的数据字典视图USER_UNUSED_COL_TABSDBA_UNUSED_COL_TABSALL_UNUSED_COL_TABS

未使用的列被视为已删除,即使它们的列数据仍保留在表行中。一列被标记后UNUSED,将无法访问该列。SELECT 查询不会检索未使用的列数据。此外,标记的列的名称和类型UNUSED在 期间不会显示DESCRIBE,可以向表中添加一个与未使用的列同名的新列。

3.实际删除这些列之前,它们将继续计入单个表中 1000 列的绝对限制。但是,与所有 DDL 语句一样,不能回滚此子句的结果。不能发出SET USED对应物来检索您拥有的列SET UNUSED此外,如果您将一LONG列标记为UNUSED,则LONG在您实际删除未使用的LONG列之前,您无法向表中添加另一列。

4.建议加上ONLINE关键字,在线业务很重要,不会阻塞(非阻塞代表dml业务操作没影响(除了删除的列),SET UNUSED就会给表加上锁,ONLINE不影响其他DML);

如果使用ONLINE关键字,以下操作现在非阻塞:

  • ALTER TABLE table-name DROP CONSTRAINT contraint-name ONLINE;
  • ALTER TABLE table-name SET UNUSED (column-list) ONLINE;
  • DROP INDEX index-name ONLINE;
  • ALTER INDEX index-name UNUSABLE ONLINE;
  • ALTER TABLE table_name MOVE PARTITION partition-name ONLINE ...;
  • ALTER TABLE table_name MOVE SUBPARTITION partition-name ONLINE ...;

以下操作在没有ONLINE关键字的情况下是非阻塞的

  • ALTER INDEX index-name INVISIBLE;
  • ALTER INDEX index-name VISIBLE;


posted @ 2021-07-14 20:11  翰墨文海  阅读(1588)  评论(0编辑  收藏  举报