最好的方法
创建一个仅包含有效数据的新表,并在其中重新创建索引,然后删除旧表。
- 使用过滤后的数据创建新表,其中 table_name 是表的名称,filter_text 是一个以“WHERE ...”开头的条件,partitionText 是一个分区子句,如果您有一个用于表的分区子句,例如
RANGE (ENDEDAT) INTERVAL ( NUMTODSINTERVAL(1,''day'') ) ( PARTITION p_first VALUES LESS THAN ( TO_DATE(''01-01-2010'',''dd-MM-yyyy'') ) ) ENABLE ROW MOVEMENT
sqlCommand := 'create table ' || table_name ||'_TMP
tablespace &TBS_NORMAL_TABLES initrans 32 ' || partitionText ||'
nologging
AS (SELECT * FROM '||table_name|| ' ' ||filter_text||')';
EXECUTE IMMEDIATE sqlCommand;
例如,约束、索引...这些可以从内置表中收集,例如 all_constraints、all_indexes。属性的移动也可以自动化,只需要应用一些重命名技巧。
execute immediate 'ALTER TABLE &Schemaowner..'||v_table_name||' RENAME TO '||v_table_name||'_OT';
execute immediate 'ALTER TABLE &Schemaowner..'||v_table_name||'_TP'||' RENAME TO '||v_table_name;
execute immediate 'DROP TABLE '||v_table_name||'_OT';
TL;关于收缩和重组表的 DR 信息
当考虑在实时生产数据库上存档大量数据时,这里提供了一些关于我的调查的信息和有用的链接。
自动收缩一些表并处理它们的错误
for i in (SELECT obj.owner,obj.table_name,(CASE WHEN NVL(idx.cnt, 0) < 1 THEN 'Y' ELSE 'N' END) as shrinkable, row_movement
FROM all_tables obj,
(SELECT table_name, COUNT(rownum) cnt
FROM user_indexes
WHERE index_type LIKE 'FUN%'
GROUP BY table_name) idx
WHERE obj.table_name = idx.table_name(+)
AND obj.owner = &Schemaowner
and obj.table_name like 'T_%' and obj.table_name not like 'TMP_%'
and NVL(idx.cnt,0) < 1)
loop
BEGIN
if i.row_movement='ENABLED' then
execute immediate 'alter table '||i.table_name||' shrink space';
else
execute immediate 'alter table '||i.table_name||' enable row movement';
execute immediate 'alter table '||i.table_name||' shrink space';
execute immediate 'alter table '||i.table_name||' disable row movement';
end if;
DBMS_OUTPUT.PUT_LINE('shrinked table: ' || i.table_name);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error while shrinking table: ' || i.table_name);
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
if SQLCODE=-10635 then
for p in (SELECT partition_name ,tablespace_name FROM user_tab_partitions WHERE table_name = 'SOME_PARTITIONED_TABLE')
loop
BEGIN
execute immediate 'alter table '||i.table_name||' MOVE PARTITION ' || p.partition_name || ' ONLINE TABLESPACE ' || p.tablespace_name || ' COMPRESS UPDATE INDEXES';
DBMS_OUTPUT.PUT_LINE('moved partition: ' || p.partition_name);
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error while moving partition: ' || p.partition_name);
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
CONTINUE;
END;
end loop;
end if;
CONTINUE;
END;
end loop;
有用的选择
可收缩表
SELECT obj.owner
,obj.table_name
,(CASE WHEN NVL(idx.cnt, 0) < 1 THEN 'Y' ELSE 'N' END) as shrinkable
FROM all_tables obj,
(SELECT table_name, COUNT(rownum) cnt
FROM user_indexes
WHERE index_type LIKE 'FUN%'
GROUP BY table_name) idx
WHERE obj.table_name = idx.table_name(+)
AND NVL(idx.cnt,0) < 1
and obj.owner='YOUR_SCHEMA_OWNER'
使收缩命令无法执行的索引
SELECT *
FROM all_indexes
WHERE index_type LIKE 'FUN%'
and owner='YOUR_SCHEMA_OWNER'
毫不妥协的可收缩表
SELECT obj.owner
,obj.table_name
,(CASE WHEN NVL(idx.cnt, 0) < 1 THEN 'Y' ELSE 'N' END) as shrinkable
FROM all_tables obj,
(SELECT table_name, COUNT(rownum) cnt
FROM user_indexes
WHERE index_type LIKE 'FUN%'
GROUP BY table_name) idx
WHERE obj.table_name = idx.table_name(+)
AND NVL(idx.cnt,0) < 1
--and obj.table_name like 'T_%' and obj.table_name not like 'TMP_%'
and obj.compression != 'ENABLED'
and obj.table_name not in (SELECT table_name FROM user_tab_partitions WHERE compression = 'ENABLED')
and obj.owner='YOUR_SCHEMA_OWNER'
收缩问题、表和/或分区的压缩
SELECT table_name,compression, compress_for FROM user_tables WHERE compression = 'ENABLED'
SELECT table_name,partition_name, compression, compress_for FROM user_tab_partitions WHERE compression = 'ENABLED' ORDER BY 1
在收缩之前/之后检查这些,测试一下
select segment_name,bytes/1024/1024 as mb,blocks from user_segments where segment_name='TABLE_NAME'
在我的例子中,我创建了一个包含几百万行的表(未分区),然后删除其中的 1/3,结果如下:
|| BYTES || BLOCKS ||
Before deletion || 105250816 || 12848 ||
After deletion || 78774272 || 9616 ||
调查和副作用
可能的副作用
https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:9536157800346457013
...以及何时应该使用重组:
http://www.dba-oracle.com/t_table_fragmentation.htm
...启用行移动,而收缩空间可以重新排列行(这意味着如果使用基于 ROWID 的作业或选择或类似的东西,那么可能会有一些惊喜)
http://www.dba-oracle.com/t_enable_row_movement.htm