測試的時候向數據庫中插入了大量的數據,測試完成后刪除了測試用戶以及其全部數據,但是數據文件卻沒有縮小。經查閱資料之后發現這是 Oracle “高水位”所致,那么怎么把這些數據文件的大小降下來呢?解決辦法如下:
概念:
表空間的相關知識請見這里,詳細的介紹了 Oracle 數據庫的存儲結構。
高水位:High Water Mark (HWM),是段(Segment)的一個指標,界定了段(Segment)曾經配置過的 block 水位。
據說,隨着數據的 insert,所使用段(Segment)的數據塊(data block)也不斷增加,這時候高水位(HWM)也隨着上升。當數據被刪除后(無論是 delete 還是 truncate table)雖然被占用的數據塊(data block)已經相應減少,但是高水位(HWM)並不會隨之下降。當高水位(HWM)下存在大量的空白數據塊(data block)時,如果發生全表掃描(Full Table Scan, FTS)就會造成很多額外的 IO。因為全表掃描(FTS)的時候讀取段(Segment)中的數據塊(data block)會一直讀取到高水位(HWM)才結束。高水位(HWM)就是段(Segment)中數據塊(data block)有沒有使用的分界線,所以全表掃描(FTS)所花費的時間不但不會因為數據的刪除而減少,反而會增加。(關於此段查詢效率的內容有待驗證,筆者未親自驗證。不過可以確定的是高水位確實不會隨着數據的刪除而下降。)
降低高水位的正確做法是先降低HWM,再確定實際占有大小,再resize數據文件。
數據文件比較多,我們用其中一個較大的文件做為 Demo,其它數據文件如法炮制即可。我選擇的文件是:D:\oracle\product\10.2.0\oradata\orcl\USERS01.DBF 1.4GB 左右。
1.登錄 sqlplus:
語法:sqlplus username/password@hostname:port/sid
例:sqlplus system/orcl@localhost:1521/orcl
2.查詢這個數據文件的編號:
SQL> select file#, name from v$datafile;
FILE# NAME
------------------------------------------------------------------------------------------
1 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSTEM01.DBF
2 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\UNDOTBS01.DBF
3 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSAUX01.DBF
4 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\USERS01.DBF
可以看到,我們要操作的數據文件的編號是4。
2.根據文件 ID 查詢這個數據文件最大數據塊(data block)的編號:(似乎這個最大編號可以代表該數據文件中數據塊的數量,這一點有待考證。)
SQL> select max(block_id) from dba_extents where file_id=4;
MAX(BLOCK_ID)
-------------
65673
3.計算該表空間實際占用的空間:
--查詢數據塊的大小,單位是 byte
SQL> select value from v$parameter where name='db_block_size'
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
db_block_size integer 8192--8192 byte = 8 kb
--接下來計算該表空間占用的物理空間
SQL> select 65673 * 8 / 1024 from dual;
65673*8/1024
------------
513.070313--實際占用的物理空間是 513MB 多點
4.最后一步,把我們的數據文件尺寸修改得比這個表空間實際占用的物理空間大點就行了:
SQL> alter database datafile 'D:\oracle\product\10.2.0\oradata\orcl\USERS01.DBF' resize 600m;
數據庫已更改。
OK,數據文件從修改前的 1.4GB 變成了 600MB。對於其它的數據文件,大家也知道如何收縮了吧?