在一個數據庫使用下面SQL找出了一批需要降低高水位線的表,其中有幾個表沒有數據,於是我打算用TRUNCATE來降低高水位線HWM
SELECT a.owner,
a.segment_name,
a.segment_type,
a.tablespace_name,
a.blocks "real block",
a.bytes / 1024 / 1024 "realSizeMB",
b.last_analyzed,
b.num_rows
FROM dba_segments a,
dba_tables b
WHERE a.owner = b.owner
AND a.segment_name = b.table_name
AND B.partitioned = 'NO'
AND b.num_rows < 5000
AND a.blocks > 1000
AND a.bytes / 1024 / 1024 > 500
ORDER BY 6 DESC
我們先看看其中一個表的空間使用情況,如下所示,結果我對該表執行了TRUNCATE後,發現高水位線HWM根本沒有變化
SQL> exec show_space('INV_MONTH_END_LOCATION', 'INVENTORY');
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 0
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 0
Full Blocks ..................... 0
Total Blocks............................ 434,176
Total Bytes............................. 3,556,769,792
Total MBytes............................ 3,392
Unused Blocks........................... 434,142
Unused Bytes............................ 3,556,491,264
Last Used Ext FileId.................... 40
Last Used Ext BlockId................... 9
Last Used Block......................... 34
PL/SQL procedure successfully completed.
SQL> exec show_space('INV_MONTH_END_LOCATION', 'INVENTORY');
Unformatted Blocks ..................... 0
FS1 Blocks (0-25) ..................... 0
FS2 Blocks (25-50) ..................... 0
FS3 Blocks (50-75) ..................... 0
FS4 Blocks (75-100)..................... 0
Full Blocks ..................... 0
Total Blocks............................ 434,176
Total Bytes............................. 3,556,769,792
Total MBytes............................ 3,392
Unused Blocks........................... 434,142
Unused Bytes............................ 3,556,491,264
Last Used Ext FileId.................... 40
Last Used Ext BlockId................... 9
Last Used Block......................... 34
PL/SQL procedure successfully completed.
當時傻眼了,難道我搞錯了, 難道TRUNCATE不會釋放存儲空間,降低高水位線?於是查了一下資料,確認TRUNCATE會釋放存儲空間,降低高水位線。那麼問題出在哪裡呢?於是我對該表重新收集了一下統計信息後發現依然如此
SQL> exec dbms_stats.gather_table_stats('INVENTORY','INV_MONTH_END_LOCATION', cascade=>true);
PL/SQL procedure successfully completed.
最後我生成了創建該表的SQL語句,終於發現了問題。如下截圖所示。initial與next決定創建segment及擴展segment,initial表示初始化時分配給該表的段大小為3,556,769,792Byte。也就是3392MB。但是已經不知道當時誰建表示設定了這個參數,於是只能DROP掉這個表,然後修改該參數重新創建該表。
另外,如果是這個情況下,使用ALTER MOVE也是不能釋放表空間,降低高水位線的。切記切記。