REFRESH MATERIALIZED VIEW
を呼び出す必要があります 関係するテーブルを変更するたびに、そうですか?
はい、PostgreSQL自体が自動的に呼び出すことはありません。何らかの方法で呼び出す必要があります。
これを行うにはどうすればよいですか?
これを達成するための多くの方法。いくつかの例を示す前に、 REFRESH MATERIALIZED VIEW
に注意してください。 コマンドはAccessExclusiveモードでビューをブロックするため、機能している間は SELECT
を実行することもできません。 テーブルの上。
ただし、バージョン9.4以降を使用している場合は、 CONCURRENTLY
を指定できます。 オプション:
REFRESH MATERIALIZED VIEW CONCURRENTLY my_mv;
これによりExclusiveLockが取得され、 SELECT
はブロックされません。 クエリを実行しますが、オーバーヘッドが大きくなる可能性があります(変更されたデータの量によって異なりますが、変更された行が少ない場合は、より高速になる可能性があります)。それでも2つのREFRESH
を実行することはできませんが コマンドを同時に実行します。
手動で更新
検討するオプションです。特に、データの読み込みやバッチ更新の場合(たとえば、長期間の後に大量の情報/データのみを読み込むシステム)、データを変更または処理する操作を最後に行うのが一般的であるため、<コードを含めるだけで済みます。>更新コード> 最後に操作します。
REFRESH操作のスケジュール
最初の広く使用されているオプションは、スケジューリングシステムを使用して更新を呼び出すことです。たとえば、cronジョブで同様の設定を行うことができます。
*/30 * * * * psql -d your_database -c "REFRESH MATERIALIZED VIEW CONCURRENTLY my_mv"
その後、マテリアライズドビューは30分ごとに更新されます。
考慮事項
このオプションは、特に CONCURRENTLY
を使用すると、非常に効果的です。 オプションですが、常に100%最新ではないデータを受け入れることができる場合に限ります。 CONCURRENTLY
の有無にかかわらず、 、 REFRESH
コマンドはクエリ全体を実行する必要があるため、 REFRESH
をスケジュールする時間を検討する前に、内部クエリの実行に必要な時間をとる必要があります。 。
トリガーで更新
もう1つのオプションは、 REFRESH MATERIALIZED VIEW
を呼び出すことです。 次のようなトリガー関数で:
CREATE OR REPLACE FUNCTION tg_refresh_my_mv()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
REFRESH MATERIALIZED VIEW CONCURRENTLY my_mv;
RETURN NULL;
END;
$$;
次に、ビューの変更を含むテーブルで、次のことを行います。
CREATE TRIGGER tg_refresh_my_mv AFTER INSERT OR UPDATE OR DELETE
ON table_name
FOR EACH STATEMENT EXECUTE PROCEDURE tg_refresh_my_mv();
考慮事項
パフォーマンスと並行性に関するいくつかの重大な落とし穴があります:
- INSERT / UPDATE / DELETE操作では、クエリを実行する必要があります(MVを検討している場合は遅くなる可能性があります)。
-
CONCURRENTLY
でも 、1つのREFRESH
それでも別のテーブルをブロックするため、関連するテーブルのINSERT / UPDATE/DELETEはシリアル化されます。
良い考えとして私が考えることができる唯一の状況は、変更が本当にまれであるかどうかです。
LISTEN/NOTIFYを使用して更新
前のオプションの問題は、同期的であり、各操作で大きなオーバーヘッドが発生することです。これを改善するには、以前と同じようにトリガーを使用できますが、これは NOTIFY
のみを呼び出します。 操作:
CREATE OR REPLACE FUNCTION tg_refresh_my_mv()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
NOTIFY refresh_mv, 'my_mv';
RETURN NULL;
END;
$$;
したがって、接続を維持し、 LISTEN
を使用するアプリケーションを構築できます。 REFRESH
を呼び出す必要性を識別するための操作 。これをテストするために使用できる優れたプロジェクトの1つはpgsidekickです。このプロジェクトでは、シェルスクリプトを使用して LISTEN
を実行できます。 、 REFRESH
をスケジュールできます として:
pglisten --listen=refresh_mv --print0 | xargs -0 -n1 -I? psql -d your_database -c "REFRESH MATERIALIZED VIEW CONCURRENTLY ?;"
または、 pglater
を使用します ( pgsidekick
内にも ) REFRESH
を呼び出さないようにするため よく。たとえば、次のトリガーを使用して、 REFRESH
にすることができます。 、ただし1分(60秒)以内:
CREATE OR REPLACE FUNCTION tg_refresh_my_mv()
RETURNS trigger LANGUAGE plpgsql AS $$
BEGIN
NOTIFY refresh_mv, '60 REFRESH MATERIALIZED VIEW CONCURRENLTY my_mv';
RETURN NULL;
END;
$$;
したがって、 REFRESH
は呼び出されません。 60秒以内に、また NOTIFY
60秒以内に何度もREFRESH
トリガーされるのは1回だけです。
考慮事項
cronオプションとして、これは少し古いデータでむき出しになる場合にのみ有効ですが、これには REFRESH
という利点があります。 本当に必要な場合にのみ呼び出されるため、オーバーヘッドが少なくなり、データは必要なときにさらに近く更新されます。
OBS:私はまだコードと例を試したことがないので、誰かが間違いを見つけたり、タイプミスしたり、試してもうまくいく(またはうまくいかない)場合は、私に知らせてください。