lo モジュールを使用したラージオブジェクトの管理 - Amazon Aurora

lo モジュールを使用したラージオブジェクトの管理

lo モジュール(拡張機能)は、JDBC または ODBC ドライバを介して PostgreSQL データベースを操作するデータベースユーザーおよび開発者向けです。JDBC と ODBC はどちらも、ラージオブジェクトの参照が変更されたときに、データベースがラージオブジェクトの削除を処理することを想定しています。ただし、PostgreSQL はそのように動作しません。PostgreSQL では、オブジェクトの参照が変更されたときにオブジェクトを削除する必要があるとは想定していません。その結果、オブジェクトはディスク上に残り、参照されません。lo 拡張機能には、必要に応じてオブジェクトを削除するための参照変更時にトリガーするために使用する関数が含まれています。

ヒント

データベースが lo 拡張機能の恩恵を受けるかどうかを判断するには、vacuumlo ユーティリティを使用して、孤立したラージオブジェクトをチェックします。アクションを実行せずに孤立したラージオブジェクトのカウントを取得するには、-n オプション (no-op) を使ってユーティリティを実行します。この方法については、下記の「vacuumlo utility」を参照してください。

Lo モジュールは Aurora PostgreSQL 13.7、12.11、11.16、10.21 以降のマイナーバージョンで利用できます。

モジュール(拡張機能)をインストールするには、rds_superuser 権限が必要です。lo 拡張機能をインストールすると、データベースに次のものが追加されます。

  • lo — これは、バイナリラージオブジェクト (BLOB) やその他のラージオブジェクトに使用できるラージオブジェクト (lo) データ型です。lo データ型は、oid データ型のドメインです。つまり、オプションの制約を持つオブジェクト識別子です。詳細については、PostgreSQL ドキュメントの「オブジェクト識別子」を参照してください。簡潔に言うと、lo データ型を使用して、ラージオブジェクト参照を保持するデータベース列を他のオブジェクト識別子 (OID) と区別できます。

  • lo_manage — これは、ラージオブジェクト参照を含むテーブル列のトリガーで使用できる関数です。ラージオブジェクトを参照する値を削除または変更すると、トリガーによってリファレンスからオブジェクト (lo_unlink) のリンクが解除されます。列がラージオブジェクトへの唯一のデータベース参照である場合にのみ、列でトリガーを使用します。

ラージオブジェクトモジュールの詳細については、PostgreSQL ドキュメントの「lo」を参照してください。

lo 拡張機能のインストール

lo 拡張機能をインストールする前に、rds_superuser 権限があることを確認してください。

lo 拡張機能をインストールするには
  1. psql を使用して、Aurora PostgreSQL DB クラスターのプライマリ DB インスタンスに接続します。

    psql --host=your-cluster-instance-1.666666666666.aws-region.rds.amazonaws.com --port=5432 --username=postgres --password

    プロンプトが表示されたら、パスワードを入力します。psql クライアントが接続し、プロンプトとしてデフォルトの管理用接続データベースである postgres=> を表示します。

  2. 次のように 拡張機能をインストールします。

    postgres=> CREATE EXTENSION lo; CREATE EXTENSION

lo データ型を使用して、テーブルの列を定義できるようになりました。例えば、ラスターイメージデータが含まれるテーブルを作成できます (images)。次の例に示すように、列 rasterlo データ型を使って、テーブルを作成できます。

postgres=> CREATE TABLE images (image_name text, raster lo);

lo_manage トリガー関数を使用してオブジェクトを削除する

lo または他のラージオブジェクト列の lo_manage 関数を使って、lo が更新または削除されたときにクリーンアップ(および孤立したオブジェクトを防ぐ)ことができます。

ラージオブジェクトを参照する列にトリガーを設定するには
  • 次のいずれかを行います。

    • 引数に列名を使用して、ラージオブジェクトへの一意の参照を含むように、各列に BEFORE UPDATE トリガーまたは BEFORE DELETE トリガーを作成します。

      postgres=> CREATE TRIGGER t_raster BEFORE UPDATE OR DELETE ON images FOR EACH ROW EXECUTE FUNCTION lo_manage(raster);
    • トリガーは、列が更新されている場合にのみ適用します。

      postgres=> CREATE TRIGGER t_raster BEFORE UPDATE OF images FOR EACH ROW EXECUTE FUNCTION lo_manage(raster);

lo_manage トリガー関数は、トリガーの定義方法に応じて、列データの挿入または削除のコンテキストでのみ機能します。データベースで DROP または TRUNCATE 式を実行しても効果はありません。つまり、孤立したオブジェクトを作成しないようにするには、削除する前にテーブルからオブジェクト列を削除する必要があります。

例えば、images テーブルを含むデータベースを削除するとします。列は、次のように削除します。

postgres=> DELETE FROM images COLUMN raster

lo_manage 関数がその列で削除を処理するために定義されていると仮定すると、テーブルを安全に削除できます。

vacuumlo を使用して孤立したラージオブジェクトを削除する

vacuumlo ユーティリティは、孤立したラージオブジェクトを識別し、データベースから削除します。このユーティリティは PostgreSQL 9.1.24 以降で使用可能です。データベースユーザーがラージオブジェクトを日常的に操作する場合は、vacuumlo をときどき実行して、孤立したラージオブジェクトをクリーンアップすることをお勧めします。

lo 拡張機能をインストールする前に、vacuumlo を使用して Aurora PostgreSQL DB クラスターにメリットがあるかどうかを評価できます。これを行うには、-n オプション (no-op) を使用して vacuumlo を実行し、以下に示すように、削除される内容を表示します。

$ vacuumlo -v -n -h your-cluster-instance-1.666666666666.aws-region.rds.amazonaws.com -p 5433 -U postgres docs-lab-spatial-db Password:***** Connected to database "docs-lab-spatial-db" Test run: no large objects will be removed! Would remove 0 large objects from database "docs-lab-spatial-db".

出力が示すように、孤立したラージオブジェクトは、この特定のデータベースでは問題になりません。

このユーティリティの詳細については、PostgreSQL ドキュメントの「vacuumlo」を参照してください。

vacuumlo の仕組みについて

vacuumlo コマンドは、ユーザーテーブルに影響や矛盾を引き起こすことなく、PostgreSQL データベースから孤立したラージオブジェクト (LO) を削除します。

コマンドの仕組みは次のとおりです。

  1. まず、vacuumlo は、データベース内のラージオブジェクトのオブジェクト ID (OID) がすべて含まれる一時テーブルを作成します。

  2. 次に、vacuumlo は、データ型 oid または lo を使用するデータベース内のすべての列をスキャンします。vacuumlo がこれらの列で一致する OID を検出すると、一時テーブルから OID が削除されます。vacuumlo は、これらのタイプに基づくドメインではなく、oid または lo という名前の列のみをチェックします。

  3. 一時テーブルの残りのエントリは孤立した LO を表し、vacuumlo によってその後安全に削除されます。

vacuumlo パフォーマンスの向上

-l オプションを使用してバッチサイズを増やすことで、vacuumlo のパフォーマンスを向上させることができます。これにより、vacuumlo は一度により多くの LO を処理できます。

システムに十分なメモリがあり、一時テーブルを完全にメモリに格納できる場合は、データベースレベルで temp_buffers 設定を大きくするとパフォーマンスが向上する可能性があります。こうするとテーブルがメモリ内に完全に格納されるため、全体的なパフォーマンスの向上を期待できます。

以下は、一時テーブルのサイズを見積もるクエリです。

SELECT pg_size_pretty(SUM(pg_column_size(oid))) estimated_lo_temp_table_size FROM pg_largeobject_metadata;

ラージオブジェクトに関する考慮事項

ラージオブジェクトを操作するときに注意すべき重要な考慮事項を以下に示します。

  • 現在、孤立した LO を削除する方法はほかにないため、Vacuumlo が唯一の解決策です。

  • レプリケーションテクノロジーを使用する pglogical、ネイティブ論理レプリケーション、AWS DMS などのツールは、ラージオブジェクトのレプリケーションをサポートしていません。

  • データベーススキーマを設計するときは、可能な限りラージオブジェクトは使用せず、代わりに bytea などの代替データ型を使用することを検討してください。

  • 孤立した LO の問題を防ぐために、少なくとも毎週定期的に vacuumlo を実行します。

  • 孤立した LO が作成されないように、ラージオブジェクトを保存するテーブルで lo_manage 関数のトリガーを使用します。