web-dev-qa-db-ja.com

pg_largeobjectテーブルにVACUUM FULLを実行できますか?

Postgres 9.1データベースに2つのテーブル(table1table2)があります。どちらもoid型です。各テーブル100万レコード。また、pg_largeobjectテーブルのサイズは約40GBです。各テーブルから90万レコードを削除し、以下のコマンドを実行しました。

vacuum full analyze table1;
vacuum full analyze table2;

それでもpg_largeobjectテーブルサイズは変更されません(自動バキュームが有効になっています)

上記のコマンドをpg_largeobjectテーブルに対しても実行する必要がありますか?何か影響はありますか?

7
Spike

あなたは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データベースから「孤立した」ラージオブジェクトを削除するシンプルなユーティリティプログラムです。

10