【実務・中級編】 ルールシステム(CREATE RULE) – PostgreSQL

PostgreSQLの「ルールシステム」という名の劇薬、使いこなせてる?

やあ。最近、PostgreSQLのクエリチューニングについて相談を受けることが増えたんだけど、その中で時々「これ、どうやって解決すればいいんだ?」と迷路に迷い込んでいるエンジニアによく遭遇するんだ。

特に、`CREATE RULE`(ルールシステム)に手を出して、その挙動に振り回されているケースがね。

正直に言うよ。PostgreSQLのルールシステムは、魔法のような力を持っている。クエリを書き換え、意図しない挙動さえも強制できる強力な機能だ。でも、「強力な機能ほど、慎重に使わないと足元をすくわれる」というのが、この世界での鉄則なんだ。

今日は、そんなルールシステムの正体と、現場で「踏み込んではいけないライン」について少し話をしよう。

—

そもそも「ルールシステム」って何者?

簡単に言うと、ルールは「クエリがプランナに渡される前の『前処理』」だ。

トリガー(TRIGGER)と混同されがちだけど、大きな違いがある。トリガーは行単位で動く「副作用」に近いものだけど、ルールはクエリそのものを別のクエリに「書き換えてしまう」んだ。

例えば、こんなケースを考えてみてほしい。

具体例:削除を「フラグ更新」にすり替える

「データは消さずに、`is_deleted`フラグを立てるだけで運用したい」という要件、よくあるよね。これをアプリケーション側で書き換えるのは面倒だし、ミスも起きやすい。そこでルールを使う。

CREATE RULE soft_delete AS
ON DELETE TO users
DO INSTEAD
UPDATE users SET is_deleted = true WHERE id = OLD.id;

これを発行した瞬間、誰かが `DELETE FROM users WHERE id = 1;` と実行しても、PostgreSQLは裏で `UPDATE users SET is_deleted = true WHERE id = 1;` に書き換えて実行する。

「お、便利じゃん!」と思ったかな? そう、便利なんだ。でも、ここからが落とし穴なんだよ。

—

なぜ「劇薬」なのか?

なぜ私がこれを「劇薬」と呼ぶか。理由はシンプルで、「プランナがクエリの意図を正確に読めなくなることがあるから」だ。

1. 予期せぬ実行計画の爆発

ルールシステムによる書き換えは、クエリが複雑になればなるほど「元のクエリとは別物」として解釈されることがある。特にJOINを含むクエリに対してルールを適用すると、プランナが最適化の糸口を見失い、Nested Loop地獄に陥ることがあるんだ。

2. 再帰的な書き換えの罠

ルールの中にルールを重ねると、クエリが無限ループに近い複雑な変換を経て、とんでもないパフォーマンス低下を引き起こすことがある。デバッグしようにも、`EXPLAIN`で見えるのは「書き換え後の最終形」だから、なぜそうなったかを追跡するのが非常に困難なんだ。

—

実務で「ルール」を使うべきタイミングは?

じゃあ、使うなという話かというと、そうじゃない。「ビューの更新」に関しては、ルールは今でも非常に強力な武器だ。

例えば、複雑なJOIN結果を返すビューに対して `INSERT` や `UPDATE` を行いたいとき、`INSTEAD OF` トリガーを使うのが一般的だけど、ケースによってはルールの方がシンプルに書けることもある。

— ビューへの書き込みを特定のテーブルへ転送するルール
CREATE RULE update_view AS
ON UPDATE TO my_view
DO INSTEAD
UPDATE base_table SET val = NEW.val WHERE id = OLD.id;

ただ、最近はPostgreSQLの機能も進化しているから、まずは以下の順で検討してほしい。

1. まずは普通に書く(Viewをそのまま使う)
2. どうしても書き込みたいなら `INSTEAD OF` トリガーを検討する
3. それでもダメなら、最終手段として「ルール」を検討する

—

先輩からのアドバイス:ルールを使うなら「ログ」を信じろ

もし君がどうしても仕事でルールを書かなきゃいけない状況になったら、次の3つを約束してくれ。

  • ドキュメントを残せ: 「なぜトリガーではなくルールにしたのか」をコメントに書け。半年後の君自身が泣くことになるぞ。
  • EXPLAIN ANALYZE を必ず叩け: 書き換え後のクエリが、どんな実行計画になっているかを確認するのは義務だ。
  • 「隠れた挙動」を減らせ: 誰かが見た時に「なぜこのクエリが動いているのか」がSQLだけを見て推測できるようにしておくこと。

ルールシステムは、PostgreSQLの深淵とも言える機能だ。面白いし、魔法のように働いてくれる。でも、その魔法は「副作用」と隣り合わせだということを、常に忘れないでいてほしい。

現場からは以上だ。何か詰まったら、またいつでも相談に来いよ。一緒に実行計画を眺めてやろう。

コメント

タイトルとURLをコピーしました