【実務・中級編】 式評価の最適化 – PostgreSQL

そのクエリ、まだ「関数」に頼ってるの? PostgreSQLの式評価を最適化して爆速にする話

どうも。最近、コードレビューをしていて「あー、ここをちょっと書き換えるだけで、このクエリ、もっと速くなるのにな」ともどかしく思うことが増えてきました。

PostgreSQLは非常に賢いデータベースです。オプティマイザは優秀ですし、放っておいてもそれなりの実行計画を立ててくれる。でもね、「データベースが頭を使わなくて済む書き方」をしてあげるだけで、パフォーマンスは劇的に変わるんです。

今回は、クエリチューニングの基本中の基本、「式評価」の最適化について少し深掘りしてみましょう。

—

1. 定数畳み込み(Constant Folding)を味方につける

まず、PostgreSQLのオプティマイザがやってくれる「定数畳み込み」の話から。これは、計算可能な式をあらかじめ計算して定数に置き換えてくれる機能です。

例えば、こんなクエリがあったとします。

SELECT FROM orders WHERE created_at > NOW() – INTERVAL ‘1 day’;

これ、実は実行するたびに計算が発生します。でも、もしこれが以下のような形だったら?

— 悪い例:計算が複雑
SELECT FROM orders WHERE price 1.1 > 1000;

これだと、行ごとに `price 1.1` という計算が走ります。もし `price` にインデックスを貼っていたとしても、計算式を挟んでしまうとインデックスが使われない(非SARGableな)状態になることが多いんです。

先輩からのアドバイス

「計算はクエリの外(アプリケーション側)でやってから投げる」のが鉄則です。
`price > 1000 / 1.1` と書き換えるだけで、PostgreSQLは `1000 / 1.1` を一度だけ計算し、あとはインデックスを引くだけのシンプルなクエリとして処理してくれます。

—

2. 複雑な関数呼び出しの「罠」

次に気をつけたいのが、WHERE句やJOIN条件での関数呼び出しです。特にユーザー定義関数(UDF)を使っている場合は要注意。

— 悪い例:行ごとに複雑な関数が走る
SELECT FROM users WHERE my_custom_hash(email) = ‘abc123…’;

PostgreSQLの関数には「Volatility(揮発性)」という概念があります。デフォルトの `VOLATILE` な関数は、たとえ同じ入力でも毎回再計算されます。つまり、100万行あれば100万回関数が呼ばれるわけです。

どう対処するか?

1. 関数を `IMMUTABLE` に設定できるか確認する
その関数が同じ引数に対して常に同じ結果を返すなら、`CREATE FUNCTION` 時に `IMMUTABLE` を指定してください。これだけで、オプティマイザは結果をキャッシュできるようになります。
2. インデックスを工夫する
どうしても関数が必要なら、「式インデックス」を使いましょう。

CREATE INDEX idx_users_hash ON users (my_custom_hash(email));

こうすれば、計算はインデックス構築時に終わっているので、検索は爆速になります。

—

3. CASE式で「ショートサーキット」を狙う

複雑な条件分岐が必要なとき、`CASE` 式を使う場面も多いですよね。ここでもちょっとした工夫で負荷を減らせます。

— 効率的な書き方
SELECT FROM items
WHERE CASE
WHEN status = ‘active’ THEN price > 100
ELSE price > 500
END;

PostgreSQLの `CASE` 式は、条件が真になった時点で評価を終了します。これをうまく使うと、重い計算を「本当に必要な時だけ」に限定できるんです。

重い計算が必要な条件があるなら、それを `CASE` の一番後ろに持ってくる(あるいは、その前に軽いチェック用の条件を置く)だけで、トータルのCPUコストは驚くほど下がります。

—

まとめ:データベースに「考えさせない」のが最大のチューニング

チューニングの極意は、「データベースが推論しなくても済むような、シンプルで明快なクエリを書くこと」に尽きます。

  • 定数は先に計算して渡す
  • 関数を使うなら、インデックスとの相性を考える
  • 重い処理は、条件分岐の後ろに隠す

これらを意識するだけで、あなたの書くクエリは、これまでとは見違えるほど軽快に動くはずです。

「なんか遅いな」と思ったら、まずは `EXPLAIN ANALYZE` を叩いて、実行計画を見てみてください。そこに必ずヒントが隠れています。もし壁にぶつかったら、またいつでも相談してくださいね。

現場からは以上です!

コメント

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