oracle⼤表在线删除列操作(altertabletable_namesetunused)
在某些情况下业务建的表某些列没有⽤到,需要进⾏删除,但是如果是数据量很⼤的⼤表,直接 alter table table_name drop column column_name;这种⽅法删除,那么将出现TM表锁,业务有可能hang住,所以不能这样⼦操作;Oracle 8i 引⼊了从表中删除列的能⼒。在此之前,有必要删除整个表并重建它。可以将列标记为未使⽤(逻辑删除)或完全删除(物理删除),下⾯介绍逻辑删除和物理删除。
⼀.逻辑删除
在⼤表上,物理删除列的过程⾮常耗时且耗费资源。决定从逻辑上删除最合适。实际上并未删除⽬标列数据或恢复这些列占⽤的磁盘空
间。但是,标记为未使⽤的列不会显⽰在查询或数据字典视图中,并且会删除其名称,以便新列可以重⽤该名称。列上定义的所有约束、索引和统计信息也将被删除。
语法:
alter table table_name set unused (column_name) ONLINE; --加上ONLINE,业务不阻塞
tabletablealter 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⼦句时要快。
当您为外部表中的列指定此⼦句时,该⼦句将透明地转换为DROP COLUMN语句。这样做的原因是,对外部表的任何操作都是元数据操作,因此两个命令的性能没有区别。
2.⽤标列的所有表UNUSED中的数据字典视图USER_UNUSED_COL_TABS,DBA_UNUSED_COL_TABS和ALL_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;

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。