クエリが「迷子」になった時、君を救う最後の切り札:pg_hint_planの話
現場でバリバリSQLを書いていると、一度は経験するよね。「なんでこのクエリ、インデックスが効いてるはずなのにフルスキャンしてるんだ?」とか、「統計情報の更新もしたのに、どうしてこんな変な結合順序を選んだんだ!」っていう絶望的な瞬間。
PostgreSQLのオプティマイザは本当に優秀で、9割以上のケースでは最適解を導き出してくれる。でも、残り1割の「どうしても言うことを聞いてくれない」クエリと対峙したとき、君ならどうする?
今回は、そんな時に最後の切り札となる「pg_hint_plan」について話そうと思う。
—
「魔法」には代償があることを忘れないでほしい
まず大前提として。`pg_hint_plan`は強力なツールだけど、あくまで「最後の手段」だ。
これを使う前に、まずは`ANALYZE`による統計情報の更新や、インデックスの設計見直し、あるいは`WHERE`句の書き方を変えることで解決できないか、徹底的に調べるべきだよ。ヒント句を埋め込むのは、いわば「対症療法」だからね。構造的な問題を隠したままヒントで固めると、データが増えた時に別のクエリが爆発するリスクがある。
……と、厳しめの前置きをしたところで、本題に入ろう。
—
pg_hint_planとは何か?
標準のPostgreSQLには、Oracleのような「ヒント句(`/+ INDEX(t1 idx_name) /`みたいなやつ)」が存在しない。PostgreSQLの哲学は「オプティマイザを信じろ」だからね。
でも、実務の現場では「いや、信じたいけど今は無理なんだ」っていう時がある。そこで登場するのがこの拡張機能だ。SQLの中にコメントとして「こう動いてくれ!」という命令を書き込めるようになる。
導入のイメージ
拡張機能をインストールして `shared_preload_libraries` に設定すれば準備完了。あとはSQLに書き込むだけだ。
/+
HashJoin(t1 t2)
SeqScan(t2)
/
SELECT FROM users t1
JOIN orders t2 ON t1.id = t2.user_id;
これだけで、プランナに「このテーブル同士はハッシュ結合して、t2はフルスキャンしてくれ」と強制できる。
—
よく使う実践的なパターン
実務で「あ、これが必要だ」となる典型的なケースをいくつか挙げておくね。
1. 結合順序を固定する(Leading)
複雑な結合で、プランナが明らかに効率の悪いテーブルから結合し始めた時によく使うよ。
/+ Leading(t1 t2 t3) /
SELECT FROM t1 JOIN t2 ON … JOIN t3 ON …
これで「t1とt2を先に結合して、その結果とt3を結合しろ」と指示できる。
2. スキャン手法を強制する(IndexScan / SeqScan)
「インデックスが貼ってあるのに、何故かSeqScanを選んでしまう」という時、原因は統計情報のズレや、データの偏りが多い。
/+ IndexScan(users idx_users_email) /
SELECT FROM users WHERE email = ‘hoge@example.com’;
これで強引にインデックスを使わせる。ただし、本当にそのインデックスが速いのか、`EXPLAIN ANALYZE`で実行計画を見比べるのを忘れないように。
—
現場で「失敗しない」ための注意点
`pg_hint_plan`を使う時に、僕がいつも後輩に伝えている「鉄則」が3つある。
- 1. 必ず`EXPLAIN`で確認する
ヒントを書いたからといって、必ずその通りに動くわけじゃない。構文ミスがあれば無視されるし、物理的に不可能なヒントはエラーにはならずスルーされる。`EXPLAIN`を叩いて、意図した実行計画になっているか確認するのは絶対だ。
- 2. バージョンアップ時の罠に注意
DBをアップグレードした際、オプティマイザの性能が向上して「ヒントがない方が速い」なんてこともよくある。ヒントは一度書いたら終わりじゃない。定期的に「このヒント、まだ必要?」と見直すタスクをバックログに入れておこう。
- 3. コメントがそのまま「ドキュメント」になる
ヒントを書きすぎると、後任のエンジニアが地獄を見る。「なぜここでヒントが必要だったのか」、その理由をSQLのコメントやチケット管理ツールに必ず残しておいてくれ。
—
まとめ
`pg_hint_plan`は、エンジニアの知識と経験をSQLに直接注入できる、最高に面白いツールだ。でも、それはあくまで「オプティマイザと対話するための手段」に過ぎない。
まずは「なぜプランナがその選択をしたのか?」を考え、実行計画を読み解く力を磨いてほしい。その上で、どうにもならない壁にぶつかった時、初めてこの「魔法」を取り出してほしいと思う。
もし君が現場で「実行計画が読めない!」と悩んでいたら、いつでも相談してくれ。データベースの深淵を一緒に覗きに行こう。
じゃあ、今日も良いクエリライフを!
コメント