「クエリが遅い!」その原因、実はGEQOの気まぐれかもしれません。
現場でPostgreSQLをいじっていると、たまに遭遇しますよね。「なんでこんな単純なクエリなのに、実行計画がめちゃくちゃなんだ?」という現象。テーブルが4つ、5つと増えていくにつれ、プランナが迷走を始める……。
そんな時、真っ先に疑うべき設定の一つが `geqo_threshold` です。今日は、このちょっとクセのある設定値と、どう付き合っていくのが「現場の正解」なのか、僕なりの考えをシェアします。
—
GEQOって一体なんだ?
PostgreSQLのプランナは、クエリが来ると「どうやって結合すれば一番速いか」を計算します。通常は「動的計画法」という手法を使って、すべての組み合わせを網羅的に計算して最短ルートを探すんです。
でも、結合するテーブル数が10個、12個……と増えていくとどうなるか。組み合わせの数は爆発的に増え、プランナの計算だけで数秒かかるなんてことになりかねません。
そこで登場するのが GEQO(Genetic Query Optimizer:遺伝的クエリ最適化) です。
これは遺伝的アルゴリズムを使って、「そこそこ速いプランを、短時間で見つけ出す」という省エネモード。要は、「完璧な解を探すのを諦めて、妥協案でサクッと実行しちゃおう」という仕組みですね。
`geqo_threshold` の役割
この「いつから省エネモードに切り替えるか」を決めているのが `geqo_threshold` です。
デフォルトでは `12` になっています。つまり、結合対象のテーブルが12個に達するまでは、PostgreSQLは必死に全パターンを計算してベストなプランを探し、12個を超えるとGEQOが発動して「近似的なプラン」を作りにいくわけです。
— 現在の設定値を確認
SHOW geqo_threshold;
なぜこれが「罠」になり得るのか?
実務でよくあるのが、「8〜10テーブルくらいの結合で、GEQOが発動していないのにプランが安定しない」ケース、あるいは逆に「中途半端に設定をいじって、プランナを混乱させる」ケースです。
特に、データ量に偏りがあるテーブルや、複雑な統計情報を持つテーブルが絡むと、GEQOの近似アルゴリズムが「とんでもない遠回り」を選択することがあります。
実践的なチューニングのヒント
もし「結合数10個くらいのクエリが異常に遅い」と感じたら、以下の手順で切り分けてみてください。
1. まずは `EXPLAIN` でコストを確認
`EXPLAIN ANALYZE` を実行して、プランナが想定しているコストと、実際の実行時間に乖離がないか見ます。
2. 一時的にGEQOを無効にしてみる
セッション単位で設定を下げて、プランがどう変わるか見てみるのが一番手っ取り早い検証方法です。
— 現在のセッションだけで閾値を下げてみる(例えば8に)
SET geqo_threshold = 8;
— この状態で再度プランを確認
EXPLAIN … ;
もしこれで劇的に実行計画が改善するなら、あなたのDBのワークロードには、デフォルトの12という閾値が少し「甘すぎる」のかもしれません。
現場のエンジニアへのアドバイス
僕が後輩によく言うのは、「GEQOをいじる前に、まずはインデックスと統計情報を見直せ」ということです。
`geqo_threshold` を調整するのは、いわば「プランナの性格を変える」行為です。根本的な解決策(インデックス不足や、`ANALYZE`不足による統計情報の劣化)を放置したままGEQOの設定をいじると、後々データ量が増えた時に、もっとひどいプランを生成するリスクがあります。
おすすめの運用ステップ:
- ステップ1: まずは `ANALYZE` を実行して統計情報を最新にする。
- ステップ2: 結合順序がおかしいなら、`JOIN` の書き方やインデックスを見直す。
- ステップ3: それでもどうしようもない「極めて複雑なクエリ」が定常的にある場合のみ、特定のセッションや関数内で `SET geqo_threshold` を使い、プランナを「矯正」する。
最後に
PostgreSQLのプランナは、今のバージョンではかなり賢くなっています。だからこそ、デフォルト値を大きく変える必要が出てくるのは、非常に珍しいケースです。
もし「GEQOをいじらないとまともに動かない」というクエリがあるなら、それはおそらく設計レベルでの複雑さが限界を超えているサインかもしれません。そんな時は無理にチューニングで解決しようとせず、「ビューを分割する」とか「一時テーブルを使って段階的に計算する」といった、SQLの構造そのものを見直す勇気を持つことも大切ですよ。
データベースは嘘をつきません。プランナが迷っている時は、僕ら人間が「こっちが近道だよ」と導いてあげる。そんな対話の感覚を、ぜひ楽しんでみてください。
それでは、また現場でお会いしましょう!
コメント