為什麼delete後磁盤空間沒有釋放而truncate會釋放?

背景

因項目需求,需要清理一批舊數據,騰出空間給新數據,讓同事負責這件事。料想會很順利,但很快找到我,並告知在postgresql中把一張大的數據表刪除掉了,查詢表的size並沒有改變。

為什麼delete後磁盤空間沒有釋放而truncate會釋放?

我震驚了,問他怎麼刪除數據表的數據的,他告訴我使用"DELETE FROM table",然後使用下面的語句進行查詢

--數據庫中單個表的大小(不包含索引)
select pg_size_pretty(pg_relation_size('表名'));
--查出所有表(包含索引)並排序
SELECT table_schema || '.' || table_name AS table_full_name, pg_size_pretty(pg_total_relation_size('"' || table_schema || '"."' || table_name || '"')) AS size
FROM information_schema.tables
ORDER BY
pg_total_relation_size('"' || table_schema || '"."' || table_name || '"') DESC limit 20

我讓他用truncate試試,他興沖沖的跑去執行了,然後告訴我這個方法是可行的。

解決方式

這件事情結束後,總覺得不踏實。不搞清楚,睡覺不踏實,那就繼續深挖挖。

delete應該沒有被真正刪除或者事務沒有完成,空間沒有釋放,重新測試了一遍,發現等了半個小時,空間也沒有釋放,應該不是事務的問題,就是沒有真正刪除,而僅僅標識為已刪除狀態。

想要釋放空間,怎麼辦呢?

postgresql提供了一個VACUUM命令,詳見https://www.postgresql.org/docs/devel/sql-vacuum.html

總結

  1. truncate的刪除效率遠遠高於delete from table
  2. Delete 是 DML, Truncate是DDL
  3. Delete 不釋放空間, Truncate釋放空間
  4. Delete 可以刪除表的部分記錄, Truncate刪除整個表的記錄
  5. Delete產生小量的redo日誌和大量的undo日誌. Truncate產生的redo和undo微乎其微。

【1】https://stackoverflow.com/questions/139630/whats-the-difference-between-truncate-and-delete-in-sql


分享到:


相關文章: