我可以對 pg_largeobject 表執行 VACUUM FULL 嗎?
我在 Postgres 9.1 數據庫中有兩個表 (
table1
, )。table2
兩者都有oid類型。每張表100萬條記錄。pg_largeobject
表大小約為 40GB 。我從每個表中刪除了 90 萬條記錄,並執行了以下命令。vacuum full analyze table1; vacuum full analyze table2;
表大小仍然沒有變化
pg_largeobject
(啟用自動真空)我是否也需要執行上述命令到
pg_largeobject
表格?它會影響什麼嗎?
你可以執行它,沒問題:
VACUUM FULL ANALYZE pg_largeobject;
甚至可能刪除一些死行。細節:
但這可能不會解決您的實際問題。
當使用Postgres的大對象工具時,大對象(“blob”:二進制大對象)本身被分解成儲存在系統表中的二進制數據塊
pg_largeobject
。PK 由兩列組成,(loid, pageno)
用於引用使用者表中的 blob。OID可以多次引用同一個 blob 。loid``oid
刪除使用者表中的行不會刪除 blob。一方面,同一個 blob 可能被多次引用。您有責任自己跟踪並實際刪除“未連結”的 blob。一種方法是使用
lo_unlink()
:SELECT lo_unlink(173454); -- deletes large object with OID 173454
由於您已經使用引用刪除了行,因此
oid
您需要更有創意來辨識未連結的 blob。假設您沒有從任何其他地方引用 blob,您可以使用此查詢來修復:SELECT lo_unlink(l.loid) FROM pg_largeobject l GROUP BY loid HAVING (NOT EXISTS (SELECT 1 FROM table1 t WHERE t.oid = l.loid)) AND (NOT EXISTS (SELECT 1 FROM table2 t WHERE t.oid = l.loid));
您需要成為超級使用者才能直接訪問
pg_largeobject
。table1
假設和中的列名table2
是oid
。基於pg_largeobject_metadata
Postgres 9.3 或更高版本的更簡單查詢(如@Daniel 評論):SELECT lo_unlink(l.oid) FROM pg_largeobject_metadata l WHERE (NOT EXISTS (SELECT 1 FROM table1 WHERE t.oid = l.oid)) AND (NOT EXISTS (SELECT 1 FROM table2 WHERE t.oid = l.oid));
pg_largeobject_metadata
是公開可讀的。但是我在 pg 9.3 之前的版本(包括 pg 9.1)中沒有看到系統表中 blob 的 OID - 至少在手冊中沒有,我現在沒有舊版本要測試。所以你可能必須使用我的第一個查詢。前後對比:
SELECT count(*) FROM pg_largeobject; SELECT pg_size_pretty(pg_table_size('pg_largeobject'));
您
VACUUM FULL
現在可以執行,然後再次測試:VACUUM FULL ANALYZE pg_largeobject;
您將對Postgres 9.1 可用的附加模組感興趣。
lo
該手冊對您的問題有準確的描述:…一個表條目可以通過 OID 引用一個大對象,但是可以有多個表條目引用同一個大對象 OID,因此系統不會因為您更改或刪除一個這樣的條目而刪除大對象。
大膽強調我的。該模組也提供了一個解決方案:
該
lo
模組允許通過將觸發器附加到包含 LO 引用列的表來解決此問題。觸發器基本上只是lo_unlink
在您刪除或修改引用大對象的值時執行。對於每個 blob在整個數據庫中僅引用一次的案例。
vacuumlo 是一個簡單的實用程序,它將從 PostgreSQL 數據庫中刪除任何“孤立的”大對象。