Postgresql

使用 DELETE 或 TRUNCATE 釋放磁碟空間?

  • December 14, 2017

一個多星期前,我刪除了 postgresql 表中的所有行(不是 via truncate,而是 with delete from ...)。Select count (*)顯示表行現在為 0。

當我現在執行查詢以查詢磁碟空間時,我仍然看到該表佔用了空間。具體來說,所有索引仍然存在並且正在佔用空間。如何擺脫它們並釋放磁碟空間?其次,當我擺脫了所有行時,為什麼它們仍然保留在首位?


以下是表格的詳細說明,以防萬一:

                                     Table "public.links_photoobjectsubscription"
    Column     |           Type           |                                 Modifiers                                  
----------------+--------------------------+----------------------------------------------------------------------------
id             | integer                  | not null default nextval('links_photoobjectsubscription_id_seq'::regclass)
viewer_id      | integer                  | not null
updated_at     | timestamp with time zone | not null
seen           | boolean                  | not null
type_of_object | character varying(15)    | not null
which_photo_id | integer                  | 
which_link_id  | integer                  | 
which_group_id | integer                  | 
which_salat_id | integer                  | 
Indexes:
   "links_photoobjectsubscription_pkey" PRIMARY KEY, btree (id)
   "links_photoobjectsubscription_seen" btree (seen)
   "links_photoobjectsubscription_updated_at" btree (updated_at)
   "links_photoobjectsubscription_viewer_id" btree (viewer_id)
   "links_photoobjectsubscription_which_photo_id" btree (which_photo_id)
Foreign-key constraints:
   "links_photoobjectsubscription_viewer_id_fkey" FOREIGN KEY (viewer_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
   "links_photoobjectsubscription_which_photo_id_fkey" FOREIGN KEY (which_photo_id) REFERENCES links_photo(id) DEFERRABLE INITIALLY DEFERRED
   "which_group_id_photoobjectsubscription" FOREIGN KEY (which_group_id) REFERENCES links_group(id) ON DELETE CASCADE
   "which_link_id_photoobjectsubscription" FOREIGN KEY (which_link_id) REFERENCES links_link(id) ON DELETE CASCADE
   "which_salat_id_photoobjectsubscription" FOREIGN KEY (which_salat_id) REFERENCES links_salatinvite(id) ON DELETE CASCADE

從文件開始VACUUM

VACUUM 有兩種變體:標準 VACUUM 和 VACUUM FULL。**VACUUM FULL 可以回收更多磁碟空間,但執行速度要慢得多。**此外,標準形式的 VACUUM 可以與生產數據庫操作並行執行。(諸如 SELECT、INSERT、UPDATE 和 DELETE 之類的命令將繼續正常執行,但在清理表時,您將無法使用 ALTER TABLE 等命令修改表的定義。) VACUUM FULL 需要獨占鎖定它正在處理的表,因此不能與該表的其他用途並行完成。因此,通常管理員應努力使用標準 VACUUM 並避免 VACUUM FULL。

您基本上需要發出一個命令來重寫整個表(來自同一個文件),

**提示:由於大量更新或刪除活動導致表包含大量死行版本時,普通 VACUUM 可能無法令人滿意。如果您有這樣的表並且需要回收它佔用的多餘磁碟空間,則需要使用 VACUUM FULL,或者 CLUSTER 或 ALTER TABLE 的表重寫變體之一。**這些命令重寫表的全新副本並為其建構新索引。所有這些選項都需要排他鎖。請注意,它們還臨時使用大約等於表大小的額外磁碟空間,因為表和索引的舊副本在新副本完成之前無法釋放。

在同一份文件中,

提示:如果您有一個定期刪除全部內容的表,請考慮使用 TRUNCATE 執行此操作,而不是使用 DELETE 後跟 VACUUM。TRUNCATE 會立即刪除表的全部內容,而不需要後續的 VACUUM 或 VACUUM FULL 來回收現在未使用的磁碟空間。缺點是違反了嚴格的 MVCC 語義

而且,從文件開始TRUNCATE

TRUNCATE 從一組表中快速刪除所有行。它與每個表上的非限定 DELETE 具有相同的效果,但由於它實際上並不掃描表,因此速度更快。此外,它會立即回收磁碟空間,而不需要後續的 VACUUM 操作。這在大表上最有用。

引用自:https://dba.stackexchange.com/questions/160760