對於一些比較大的數據文件,想回收一般就採用:先清除這個數據文件的數據,然後resize大小
實驗:
先創建一個測試表空間
create tablespace test datafile '/u01/app/oracle/oradata/U01/datafile/test.dbf' size 10M autoextend on next 50M;
然後爲這個表空間創建一個表
create table test1 tablespace test as select * from dba_objects;
現在查看這個表空間數據文件大小
select BYTES/1024/1024,MAXBYTES/1024/1024 from Dba_Data_Files where tablespace_name ='TEST';
現在查看文件大小還是開始的10M
接着添加數據:
insert into test1 select * from dba_objects ;
然後 commit;
現在再查看這個數據文件的大小,看看是不是成了60M了
再查看一下,數據文件具體用的大小情況:
SELECT UPPER(F.TABLESPACE_NAME) "表空間名", D.TOT_GROOTTE_MB "表空間大小(M)", D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空間(M)", TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') || '%' "使用比", F.TOTAL_BYTES "當前空閒空間(M)", (SELECT free_space_mb+free_allocate_mb FROM dba_tablespace_free a where a.tablespace_name= f.tablespace_name) "總剩餘空間", F.MAX_BYTES "最大塊(M)" FROM (SELECT TABLESPACE_NAME, ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES, ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES FROM SYS.DBA_FREE_SPACE GROUP BY TABLESPACE_NAME) F, (SELECT DD.TABLESPACE_NAME, ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB FROM SYS.DBA_DATA_FILES DD GROUP BY DD.TABLESPACE_NAME) D WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME and f.tablespace_name='TEST' ORDER BY 3 desc;
從這個看出實際用的並沒有那麼多,然後再把這個文件增加,接着添加數據
insert into TEST1 select * from test1 ; commit;
現在再查看下數據文件具體的大小
然後根據這個實際佔用大小回收數據文件
select FILE_ID from dba_data_files where tablespace_name='TEST'; alter database datafile X resize XX M;
現在是可以回收的。
回收之後再查看下,數據文件佔用的具體大小。
這時大小是肯定改變了。
然後再創建一個表2
create table test2 tablespace test as select * from dba_objects;
再看下具體佔用空間,看看是不是已經改變了。
然後清除表1的數據
truncate table test1;
清除之後,接着再查看數據文件具體的大小
SELECT UPPER(F.TABLESPACE_NAME) "表空間名", D.TOT_GROOTTE_MB "表空間大小(M)", D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空間(M)", TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES) / D.TOT_GROOTTE_MB * 100,2),'990.99') || '%' "使用比", F.TOTAL_BYTES "當前空閒空間(M)", (SELECT free_space_mb+free_allocate_mb FROM dba_tablespace_free a where a.tablespace_name= f.tablespace_name) "總剩餘空間", F.MAX_BYTES "最大塊(M)" FROM (SELECT TABLESPACE_NAME, ROUND(SUM(BYTES) / (1024 * 1024), 2) TOTAL_BYTES, ROUND(MAX(BYTES) / (1024 * 1024), 2) MAX_BYTES FROM SYS.DBA_FREE_SPACE GROUP BY TABLESPACE_NAME) F, (SELECT DD.TABLESPACE_NAME, ROUND(SUM(DD.BYTES) / (1024 * 1024), 2) TOT_GROOTTE_MB FROM SYS.DBA_DATA_FILES DD GROUP BY DD.TABLESPACE_NAME) D WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME and f.tablespace_name='TEST' ORDER BY 3 desc;
這個和上面的一樣。。。。
看下執行結果實際佔用的大小是不是已經改變。
然後現在執行回收數據
alter database datafile X resize XXM;
是不是報錯了。。。。
爲什麼呢?
因爲現在在文件中只是數據沒有了,但是塊號還沒有改變,也就是block_id還沒有改變,可以通過查到
select segment_name,block_id,blocks FROM dba_extents where Tablespace_name ='TEST' order by block_id desc;
這個返回結果意思是:block_id 是這個segment_name段所對應的一個區的起始塊號,對應的這個區裏面有連續的blocks個塊
然後總共的塊數就是這個段所佔用的空間,也就是總共有多少個塊。
現在塊的編號還沒有改變,所以不能回收大小。
需要執行:
alter table test2 move;
這個意思就是說重新分佈表2的塊號,使高水位線降低。然後回收數據文件的大小
再執行:
alter database datafile X resize XXM;
現在就可以回收了。。。。