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

我震驚了,問他怎么刪除數據表的數據的,他告訴我使用"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
總結
- truncate的刪除效率遠遠高於delete from table
- Delete 是 DML, Truncate是DDL
- Delete 不釋放空間, Truncate釋放空間
- Delete 可以刪除表的部分記錄, Truncate刪除整個表的記錄
- Delete產生小量的redo日志和大量的undo日志. Truncate產生的redo和undo微乎其微。
參考資料
【1】https://stackoverflow.com/questions/139630/whats-the-difference-between-truncate-and-delete-in-sql