硬盤空間不足,打算刪除數據庫中的多余數據,但刪除數據后,硬盤硬盤空間不能釋放。
【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'