Postgres 9.1データベースに2つのテーブル(table1
、table2
)があります。どちらもoid型です。各テーブル100万レコード。また、pg_largeobject
テーブルのサイズは約40GBです。各テーブルから90万レコードを削除し、以下のコマンドを実行しました。
vacuum full analyze table1;
vacuum full analyze table2;
それでもpg_largeobject
テーブルサイズは変更されません(自動バキュームが有効になっています)
上記のコマンドをpg_largeobject
テーブルに対しても実行する必要がありますか?何か影響はありますか?
あなたはcan実行します、問題ありません:
_VACUUM FULL ANALYZE pg_largeobject;
_
一部のデッドローを削除することもできます。詳細:
しかし、おそらくnotがあなたの実際の問題を解決するでしょう。
ラージオブジェクト Postgresの機能 を使用すると、ラージオブジェクト( "blob":バイナリラージオブジェクト)自体がシステムテーブル_pg_largeobject
_に格納されているバイナリデータのチャンク。 PKは2つの列で構成されます_(loid, pageno)
_、loid
はユーザーテーブルのblobを参照するために使用されるoid
です。同じblob canはOIDによって何度も参照されます。
ユーザーテーブルの行を削除するとnotは削除されます。まず、同じblobが複数回参照される可能性があります。追跡し、実際に「リンクされていない」ブロブを自分で削除するのはあなたの責任です。 1つの方法は 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
_に直接アクセスするには、 superuser である必要があります。 _table1
_および_table2
_の列名がoid
であると仮定します。 Postgresの _pg_largeobject_metadata
_ に基づくより単純なクエリ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
_は一般に読み取り可能です。しかし、OIDは表示されません ((pg 9.1)を含む) -少なくともマニュアルにはありません、現在テストする古いバージョンがないので、おそらく最初のクエリを使用する必要があります。
前後の比較:
_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を参照する複数のテーブルエントリが存在する可能性があるため、変更または削除しただけではシステムはラージオブジェクトを削除しませんそのようなエントリの1つ。
大胆な強調鉱山。モジュールも解決策を提供します:
lo
モジュールでは、LO参照列を含むテーブルにトリガーをアタッチすることで、これを修正できます。ラージオブジェクトを参照する値を削除または変更するたびに、トリガーは基本的に_lo_unlink
_を実行します。
各blobが参照されるユースケースの場合exactly DB全体で1回。
そして明らかに @ Danielについても同様 ) vacuumlo
:
vacuumloは、PostgreSQLデータベースから「孤立した」ラージオブジェクトを削除するシンプルなユーティリティプログラムです。