(转) Delete/Truncate删除,释放表空间、降低高水位线、resize释放磁盘空间相关优化

硬盘空间不足,打算删除数据库中的多余数据,但删除数据后,硬盘硬盘空间不能释放。
【delete后用:alter table table_name move    truncate后用:alter table table_name deallocate unused 均不可解决】

解决方法:

--delete/truncate删除,释放表空间、降低高水位线、resize释放磁盘空间相关优化汇总
--查询DBF文件、数据库空间、高水位线占用情况

select /*+ ordered use_hash(a,b,c) */
 a.file_id,
 a.file_name,
 a.tablespace_name,
 a.filesize,
 b.freesize,
 (a.filesize - b.freesize) usedsize,--使用空间
 c.hwmsize,
 c.hwmsize - (a.filesize - b.freesize) unsedsize_belowhwm,--未使用空间
 a.filesize - c.hwmsize canshrinksize--文件大小
  from (select tablespace_name,file_id, file_name, round(bytes / 1024 / 1024) filesize
          from dba_data_files) a,
       (select file_id, round(sum(dfs.bytes) / 1024 / 1024) freesize
          from dba_free_space dfs
         group by file_id) b,
       (select file_id, round(max(block_id) * 8 / 1024) HWMsize--高水位线
          from dba_extents
         group by file_id) c
 where a.file_id = b.file_id
   and a.file_id = c.file_id
 order by unsedsize_belowhwm desc

--查询【各用户】【表空间】数据存储空间占用大小(用户与表空间对应关系)

select owner,tablespace_name ,sum(bytes)/1024/1024 from dba_segments group by owner,tablespace_name

--查询当前用户【表】数据存储空间占用大小

select segment_name, bytes/1024/1024 
from user_segments 
where segment_type = 'TABLE';

--查询当前用户【所有对象】数据存储空间占用大小

select segment_type, Segment_Name, Sum(bytes) / 1024 / 1024
  From User_Extents
 Group By Segment_Name, segment_type

--查询【表空间】与【DBF】对应关系与存储情况

select tablespace_name, file_id, file_name,
round(bytes/(1024*1024),0) total_space
from dba_data_files
order by tablespace_name;

--删除表数据

truncate table ZW_FZHSZD
TRUNCATE TABLE JC_ASSETS_ADD  --DROP STORAGE

--分析(不分析,会导致下面步骤查询表的高水位线时候数值会不准)

ANALYZE TABLE ZW_FZHSZD ESTIMATE STATISTICS;

--查询表的水位分配情况

SELECT blocks, empty_blocks, num_rows 
 FROM user_tables 
 WHERE table_name = 'ZW_FZHSZD';

--TRUNCATE后可释放表数据库空间,表默认把TRUNCATE数据前的空间大小作为初始空间大小,表的高水位线不会降低,需要Shring收缩表的大小(下面详解)后方可降低表的水位线

--释放/收缩表数据库空间

--alter table tablename move --选择性操作,delete后可通过此方法释放数据库空间,但此操作MOVE时需要双倍的表空间,大表有可能会导致高水位线提高,而且如果表上有索引的

话,需要重构索引,不建议使用

alter table tablename deallocate unused keep 0;--成功释放数据库空间,但高水位线不降低(表的高水位线降低,表空间的不降低??)

alter table JC_ASSETS_CHANGE enable row movement;--开启movement功能
alter index xx rebuild--movement后需要重建索引(未验证可行性)
ALTER TABLE USERS SHRINK SPACE --cascade --成功收缩表的数据库空间为最小值,但【表空间】水位有时降低、有时不降低,原因不详

--回缩索引为最小值(选择性操作)

ALTER INDEX INDEXINDEX1_FZHSZD  SHRINK SPACE

--查询最大可resize空间

select a.file#,
a.name,
a.bytes / 1024 / 1024 CurrentMB,
ceil(HWM * a.block_size / 1024 / 1024) Resizeto,
(a.bytes - HWM * a.block_size) / 1024 / 1024 releaseMB,
'alter database datafile ''' || a.name || ''' resize ' ||
ceil(HWM * a.block_size / 1024 / 1024) || 'M;' ResizeCmd
from v$datafile a,
(select file_id, max(block_id + blocks - 1) HWM
from dba_extents
group by file_id) b
where a.file# = b.file_id(+)
and (a.bytes - HWM * a.block_size) > 0
order by 5


--Resize释放硬盘空间(resize值必须大于高水位线,所以降低水位线非常重要)

ALTER DATABASE DATAFILE 'C:\APP\ADMINISTRATOR\ORADATA\ORCL\USERS01.DBF' resize 1000M;

--释放HWM上面的未使用空间,但是并不会释放HWM下面的自由空间,也不会移动HWM的位置.

 Alter  table table_name deallocate unused

终极方法:把表空间A内所有对象(表、索引)移动到表空间B,然后Resize 表空间A为最少值(表空间内所有对象移走后高水位线会降到最低),然后再把对象从表空间B移回表空间A(测试可用,但不知道有没副作用)

PS:
【清理临时表空间方法】

ALTER TABLESPACE 临时表空间名 SHRINK SPACE KEEP 512M
EMP:ALTER TABLESPACE TEMP_FMMS2 SHRINK SPACE KEEP 512M

--表空间DBF文件大小

select bytes/1024/1024  free_size from dba_data_files where tablespace_name='USERS';

--表空间空闲空间

select  SUM(BYTES/1024/1024) total_size from dba_free_space where tablespace_name='USERS';

--表空间水位线

select max(block_id)*8/1024 "m size" from dba_extents where tablespace_name='USERS'

猜你喜欢

转载自www.cnblogs.com/tzhyy/p/9641395.html