針對一張無資料的大表執行 TRUNCATE TABLE,預期釋放空間並將高水位線(HWM)重置至初始區塊,但實際 DBMS_SPACE.SHOW_SPACE 顯示 Total Blocks、Total Bytes 完全不變,Unused Blocks 依然接近總區塊數。
STORAGE (INITIAL 3556769792 NEXT ...) —— INITIAL 直接指定了 3.3 GB。INITIAL 定義段創建時最小分配區塊數。即使表無資料,段創建瞬間即分配該大小的 Extent。TRUNCATE TABLE 行為(預設 DROP STORAGE):
ALTER TABLE ... MOVE 同樣無法釋放 INITIAL 區塊,因 MOVE 重建段時同樣遵循 STORAGE 子句。-- 查看段儲存屬性
SELECT OWNER, SEGMENT_NAME, INITIAL_EXTENT/1024/1024 INITIAL_MB, NEXT_EXTENT, MIN_EXTENTS, EXTENTS
FROM DBA_SEGMENTS
WHERE SEGMENT_NAME = 'INV_MONTH_END_LOCATION';
-- 模擬 SHOW_SPACE 核心邏輯
SELECT DBMS_SPACE.SPACE_USAGE('INVENTORY','INV_MONTH_END_LOCATION','TABLE') FROM DUAL;
-- 1. 導出結構與資料(若有)
CREATE TABLE INV_MONTH_END_LOCATION_NEW AS SELECT * FROM INV_MONTH_END_LOCATION WHERE 1=0;
-- 2. 明確指定合理 INITIAL(如 64K 或 1M)
ALTER TABLE INV_MONTH_END_LOCATION_NEW STORAGE (INITIAL 1M NEXT 1M MINEXTENTS 1);
-- 3. 切換
DROP TABLE INV_MONTH_END_LOCATION;
RENAME INV_MONTH_END_LOCATION_NEW TO INV_MONTH_END_LOCATION;
TRUNCATE TABLE ... DROP ALL STORAGE(11gR2+)TRUNCATE TABLE INV_MONTH_END_LOCATION DROP ALL STORAGE;
-- 強制釋放包含 INITIAL 在內的所有 Extents,段變為空,下次插入重新分配。
-- 注意:此語法需 11.2.0.2+,且表不能有啟用的外鍵引用。
ALTER TABLE ... DEALLOCATE UNUSED(輔助手段)ALTER TABLE INV_MONTH_END_LOCATION DEALLOCATE UNUSED KEEP 1M;
-- 僅能釋放 HWM 以上未使用區塊,無法突破 INITIAL 限制。
DBA_SEGMENTS 發現異常大 INITIAL_EXTENT 的段,納入整治清單。DROP ALL STORAGE。本案例揭示了儲存參數 INITIAL 對段生命週期的強約束力,也是「為什麼 TRUNCATE 沒瘦身」的經典教科書級答案。