LoginSignup
14
7
お題は不問!Qiita Engineer Festa 2024で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

PostgreSQL の Materialized Views は直接 DELETE できない

Last updated at Posted at 2024-06-10

はじめに

エンジニアとして入社してから 1 ヶ月経った頃,プロダクトで扱っているユーザの不必要になったデータの総削除機能の開発タスクをやらせてもらいました.

このタスクで,データが入っている PostgreSQL のテーブルに対して DELETE することで順調に進んでいましたが,Materialized View では同じ操作でうまくいきませんでした.

この記事では,Materialized View にあるデータをどうすれば削除できるのかを紹介します.

Materialized View でデータを DELETE 句で削除してみる

今回のタスクでは,ユーザに紐づく user_id のようなカラムを持っているテーブル・Materialized View を対象に削除機能開発を行いました.

テーブルに対して DELETE 句で削除する

まず,user_id のカラムを持つテーブルを以下で探します.

SELECT table_name
FROM information_schema.columns
WHERE column_name = 'user_id';
table_name
----------
table1
table2
...

上記の結果を利用して,以下のようにテーブル内のデータを削除します.

DELETE FROM table1;

これは問題なく削除されます.

Materialized View に対して DELETE 句で削除する

同じく,user_id のカラムを持つ Materialized View を以下で探します.

SELECT c.relname AS table_name
FROM pg_class c INNER JOIN pg_attribute a ON c.oid = a.attrelid
WHERE c.relkind = 'm' AND a.attnum > 0 AND NOT a.attisdropped AND a.attname = 'user_id';
table_name
----------
matview1
matview2
...

上記の結果を利用して,テーブルと同じようにデータを削除してみます.

DELETE FROM matview1;

すると,エラーが返ってきてしまいます.

ERROR: cannot change materialized view "matview1"

Materialized View は置換する必要がある

改めて Materialized View とは,PostgreSQL 16 のドキュメントによると,ビューと同じルールシステムを用いているが結果をテーブルの形で保持しているもの,です.

Materialized views in PostgreSQL use the rule system like views do, but persist the results in a table-like form.

テーブルと違い,Materialized Views は作成後に直接 update することができません.これが理由で直接 DELETE ができませんでした.

The main differences between [materialized views] and [tables] are that the materialized view cannot subsequently be directly updated.

このため,以下のクエリで Materialized View の内容を置換する必要があります.1

REFRESH MATERIALIZED VIEW matview1;

補足:PostgreSQL での置換は完全リフレッシュされる

REFRESH MATERIALIZED VIEW コマンドの動作としては,PostgreSQL 16 のドキュメントから,Materialized View の内容を「完全」に置き換える,と書かれてあります.

REFRESH MATERIALIZED VIEW completely replaces the contents of a materialized view.

完全リフレッシュの欠点としては,少数のデータを更新する際においても,全データの置換が実行されるため,処理時間が多くかかってしまいます.

この問題に対応するため,PostgreSQL 13 から拡張機能として pg_ivm が利用できます.IVM (Incremental View Maintenance) と呼ばれる手法で,増分変更のみを計算して置換します.

Incremental View Maintenance (IVM) is a way to make materialized views up-to-date in which only incremental changes are computed and applied on views rather than recomputing the contents from scratch.

おまけ: 特定のカラム名を持つテーブルを探す際に用いた情報について

指定のカラムが含まれるテーブル・Materialized View を取得する際に,information_schemapg_classpg_attribute を参照していました.これらの情報は今回の開発環境特有のものではなく,PostgreSQL が提供するものです.

information_schema について

information_schema は,データベースに定義されているオブジェクトに関する情報を保持している複数のビューで構成されているものです.

The information schema consists of a set of views that contain information about the objects defined in the current database.

また,このスキーマは標準 SQL に準拠しているため,PostgreSQL 固有の機能に関する情報は含まれません.

pg_ で始まる情報について

PostgreSQL は多くの RDMS のように,スキーマメタデータや内部的な情報を格納している system catalogssystem views を持っています.どちらも pg_ で始まる名前のテーブル・ビューになっています.

The system catalogs are the place where a relational database management system stores schema metadata, such as information about tables and columns, and internal bookkeeping information.

今回利用した,pg_class はテーブルを含むカラムを持っているオブジェクトについての情報を,pg_attribute はテーブルカラムについての情報を格納しているものです.指定カラムが含まれる Materialized View はこれらの情報を利用して取得していました.

まとめ

Materialized View のデータを削除(置換)する方法を紹介しました.REFRESH MATERIALIZED VIEW で更新できるのを忘れずに!

  1. 日本語版 PostgreSQL 16 ドキュメントより, REFRESH コマンド操作を「置換」と表現しています.

14
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
7