81%速いクエリプラン — 4BモデルがPostgresに勝った条件
81%速いクエリプラン — 4BモデルがPostgresに勝った条件
これは学習済みオプティマイザの勝利なのか、それとも実測を伴う探索の勝利なのか?
導入
2026年9月16日、Rohan Bansalの記事「Training a 4B model to produce 81% faster query plans than Postgres」がHacker Newsで702ポイントを集めた。副題は「Qwenにエージェント型強化学習でクエリ最適化を学ばせる方法」である。著者はRecurse Centerでのサバティカル中にこの実験を行い、コードをGitHubのpolyphilz/qorlリポジトリで公開している。
要点はこうだ。4B規模のオープンウェイトモデルに、Postgresのプランナ統計やプランを参照するツールを持たせ、pg_hint_planのヒントでプランを変える候補を提出させる。当初は113クエリ中99件で有効なプランすら出せなかったモデルが、GPT-6 Astraの軌跡を蒸留したSFTとそれに続く強化学習を経て、Join Order Benchmark(JOB)で幾何平均1.81倍の高速化を達成したという。総費用は約1,200ドルだった。
タイトルの数字は強烈である。だが記事を最後まで読むと、その1.81倍はかなり具体的な条件の下で出た値だとわかる。本稿ではその条件を一つずつほどき、学習型クエリ最適化という古い研究の流れの中でこの実験がどこに立つのか、そして実務者が平均の高速化より先に問うべきことは何かを考える。
現象分析 — 1.81倍はどこから来たのか
まず記事が定義した問題から見ていこう。クエリオプティマイザの中核的な難題は結合順序であり、記事はこれがNP困難であるという1984年のIbarakiとKamedaの結果を引用している。テーブル3つの結合でさえ、結合木、入力の向き、結合アルゴリズム、スキャン方式を掛け合わせると4,608通りの実行方法があり、12テーブルになれば組み合わせは天文学的に膨らむ。Postgresはこれを動的計画法で枝刈りし、12個以上の結合には遺伝的アルゴリズムを使うと記事は説明する。
より根本的な問題はカーディナリティ推定である。プランナは実際に結合を実行して行数を数えることができないので、pg_statisticの頻度とヒストグラムから推定する。結合では、あるテーブルの値の分布が別のテーブルにも一様に当てはまると仮定するが、この仮定が崩れると初期の結合の誤差が木全体に波及する。記事の例では、日本の会社が全体の5%でありながら映画の50%を出していたとすると、プランナの選ぶ順序が実際にはより悪い順序になってしまう。
著者の問題設定は巧みだ。彼はモデルでより良いカーディナリティ推定器を作る方向を早々に捨てた。数十年分の推定研究と戦うことになるうえ、推論レイテンシだけでもPostgresの超高速なプランナには追いつけないという判断である。代わりに、同じ分析クエリが何千回も繰り返し実行されるワークロードを狙った。学習と探索のために当該クエリを数十〜数百回実行するコストがかかっても、繰り返し実行全体で償却すれば得になるという論理だ。一回限りのクエリでPostgresに勝つことが目的ではない、と記事は明言している。
では数字を見よう。最終的な1,200回更新のRLチェックポイントをJOBの113クエリに対してクエリあたり3回実行したとき、記事の表は3つの選択方式を並べている。
- 各軌跡でモデル自身が選んだ候補:339軌跡ベースで幾何平均1.40倍、総ワークロード1.24倍、改善119件、退行7件
- 各軌跡内で予備計測値が最も良い候補(1.05倍超のときのみ、そうでなければデフォルトプラン):1.44倍、1.29倍、改善129件、退行1件
- 3軌跡全体、つまり最大15候補の中で予備計測値が最も良いもの:113クエリベースで1.81倍、1.81倍、改善68件、退行0件
タイトルの81%は3行目である。結論部の「総レイテンシ44.7%削減」も同じ行から来た値で、記事は脚注でこれがクエリあたり3回試行したbest-of-15の計測であると明かしている。1回の実行、モデル自身の選択で見れば数字は1.40倍だ。クエリあたり1軌跡で評価した1,200回チェックポイントの結果は1.41倍、退行2件だった。
計測環境も押さえておく必要がある。データはディスク上8.5GBのIMDbのサブセットで、Postgresコンテナ4つがそれぞれ4コアとメモリ8GBを割り当てられた。著者は計測ノイズを減らすためにshared_buffersを128MBから2GBに上げ、その結果、中央値のクエリのワーキングセットがPostgres自身のキャッシュに完全に常駐するようになった。各クエリはバッファカウンタが安定するまでウォームアップしてから計測した。つまりこの結果は、メモリに載った読み取り専用の分析クエリと、温まったキャッシュという条件の上での値である。
深層分析 — 平均が覆い隠すもの
1.81倍を解釈する鍵は2つの設計判断にある。一つは最終選択が実測に基づいていること、もう一つはスコアがクリッピングされた幾何平均であることだ。
第一に、best-of-15の「退行0件」は、モデルの判断力というより計測フィルタの性質に近い。各候補は1回ウォームアップして1回計測した予備値を受け取り、1.05倍を超えなければデフォルトプランに戻される。実際に実行して速かったものだけを残す構造なのだから、退行がふるい落とされるのは当然の帰結である。モデル自身の選択の行で339件中7件の退行があったことがこれを裏付ける。整理すると、このシステムの実際の単位は「モデル」ではなく、「モデルが候補を出し、データベースがそれを実行して採点するループ」なのだ。
第二に、スコアの式である。記事は最終計測で候補とデフォルトプランを交互に3ペア実行し、それぞれの中央値の比を0.1倍から10倍の間にクリッピングする。著者は極端な改善や退行が幾何平均を左右しないようにするための仕掛けだと説明する。学習シグナルとしては合理的だが、運用の観点で読むと意味が変わる。あるクエリが50倍遅くなっても、スコア上は10倍遅くなったとしか記録されない。幾何平均はまたクエリごとに同じ重みを与えるため、5分かかるクエリの半減と25秒のクエリの倍増が相殺されることを、記事自身が例に挙げている。著者が総ワークロードの高速化を併記した理由はここにある。
テールレイテンシの観点で最も危険なのは平均ではなく最悪ケースである。素の4Bモデルの評価で有効だった新規プラン6つのうち5つは1.02倍〜1.30倍の改善だったが、1つは0.05倍、つまり約20倍遅かった。学習がこうしたテールをどれだけ減らしたかは退行件数では見えるが、退行の大きさの分布は記事の表に出てこない。
この問題は、学習型クエリ最適化の研究が以前から格闘してきた点でもある。2019年のNeoは深層ニューラルネットワークで実行計画を直接生成する学習型オプティマイザで、PostgreSQLのような単純なオプティマイザからブートストラップしても商用オプティマイザに匹敵する性能に達しうると要旨で述べている。翌年のBaoは方向を変えた。Baoの要旨は、既存の学習型アプローチが学習オーバーヘッド、変化への適応不能、悪いテール性能のために実用的な利益が少なかったと診断し、プランを直接作る代わりに既存のオプティマイザにクエリごとのヒントを与える方式を採った。木畳み込みニューラルネットワークとThompsonサンプリングを組み合わせ、テールレイテンシを含むエンドツーエンドの実行性能を改善したというのがその主張である。
今回の実験は構造的にBaoの子孫だ。既存のオプティマイザを置き換えず、pg_hint_planのヒントで舵を取る。著者も次のステップとして、Baoスタイルの構造化されたヒント探索が4Bモデルより効果的かどうか比較したいと書いている。違うのは、ヒントを選ぶ主体が小さな分類器ではなく、ツールを呼び出す言語モデルのエージェントだという点だ。そしてこの違いこそがHacker Newsでの議論の中心だった。
Hacker Newsの反応は大きく3つに分かれた。一つ目は計測条件への疑問である。あるユーザーは、メモリに丸ごと載る8GBのデータセット、それより小さく制限されたshared_buffers、計測前のウォームアップ、読み取り専用のSELECTという条件を列挙し、より大きな規模や現実的なOLTPワークロードでもこれらのプランがPostgresのヒューリスティクスより優れているかは言いがたいと書いた(直接の引用ではなく、コメントの要旨の要約、@refibrillator)。別のユーザーは、モデルが好んで使った設定にrandom_page_cost=1.1があることを指摘した。デフォルト側でこの値が適切でなければ、回転ディスクでない環境ではプランナがひどいプランを選びうるので、それだけで差の大部分が説明できるかもしれないという疑念である(直接の引用ではなく、コメントの要旨の要約、@zacmps)。記事はshared_buffersとwork_memの調整には触れているが、デフォルトプラン側でrandom_page_costを調整したという記述はない。この疑念は記事の中で反論されないまま残っている。
二つ目はコストの会計だ。あるユーザーは、約95時間のH100レンタルとAPI費用がベンチマークの数字に含まれていないだろうと指摘し、数時間かけてモデルを更新し直す必要があるならそれを許容できるのかと問うた(直接の引用ではなく、コメントの要旨の要約、@Someone)。別のユーザーは、実運用のプランナの本当の制約は、プランニング時間と実行時間の合計を生きた統計の上で縮めることであり、このプロジェクトはそのどちらも扱っていないと批判した(直接の引用ではなく、コメントの要旨の要約、@perrygeo)。ただしこれは、著者が最初から繰り返し実行されるクエリに範囲を絞っていることを考えれば、半分だけ有効な批判である。
三つ目は道具の選択だ。なぜよりによって言語モデルなのかという問いが何度も出た。あるユーザーは、SQLとプランヒントという小さく制約された言語の間の写像を学ぶのに、膨大なテキストで学習したモデルがなぜ必要なのか、実データの特徴を数値として入力するずっと小さなニューラルネットワークの方が適切ではないかと問うた(直接の引用ではなく、コメントの要旨の要約、@topaz0)。ヒントが必要になるケースの大半は統計が間違っているからであり、ヒントは問題を覆い隠すだけで、データの形が変われば逆効果になりうるというDBA視点の指摘もあった(直接の引用ではなく、コメントの要旨の要約、@sgarland)。
展望と示唆
この実験が実際に証明したことは何か。記事の結論は、「企業はデータを持っており、RL環境を構築して小さなオープンウェイトモデルをニッチなドメイン固有タスクで学習させることは少額で可能だ」という仮説である。この仮説に対しては、実験はかなり説得力のある証拠になっている。ハーネスすら理解できなかった4Bモデルが1,200ドルほどで有効候補率101/113に達し、その過程の試行錯誤 — 過酷な無効ペナルティのせいでモデルがデフォルトプランばかり返すようになったこと、素のGRPOがグループ平均より「ましな」ロールアウトを強化してしまったこと、検証損失が横ばいなのに振る舞いが変わったこと — がすべて記録されている。
計測エンジニアリングの部分もそれ自体に価値がある。著者はjob-13bというクエリの20回の実行が186〜204msと227〜253msの2つの塊に分かれることを発見し、3ペアの中央値方式では実際には同一のプランが偽の改善や悪化と判定されうることを計算した。そこで変動係数の代わりに「報酬が騙される率」そのものを最小化の対象にした。shared_buffers 128MBでは平均no-opエラー率が5.0〜5.4%だったが、2GBでは1.2〜1.8%まで下がった。実行時間を報酬に使うあらゆるシステムが借りていける方法論である。
一方で、「Postgresより81%速いクエリプランナ」という読み方をこの実験は証明していない。実務に移すなら、次の問いが先に来る。
- 比較のベースラインはチューニング済みのPostgresか。random_page_cost、統計対象の拡張、インデックス設計を先に手入れしたデフォルトプランと比べてはじめて、モデル固有の寄与が見える。
- 退行の大きさの分布はどうか。退行件数だけでなく、最悪のクエリが何倍遅くなったのかをクリッピング前の値で見る必要がある。
- データが変わったら何が起きるか。ヒントはプランを固定する。データ分布が移動すれば、今日の最適なヒントが明日の退行になる。Hacker Newsであるユーザーが描いた「LLMプランナが今回はインデックスを見逃して本番DBが固まった」という場面に、別のユーザーは「LLM」を外してただの「クエリプランナ」と言っても同じように成り立つと返した(直接の引用ではなく、コメントの要旨の要約、@2001zhaozhao、@malisper)。もっともな指摘だが、そうであるなら必要なのは、より賢い生成器よりもプラン変更を検知して巻き戻す運用の仕組みである。
- 計測ループを運用環境で回せるか。このシステムの性能は候補を実際に実行してみることから生まれる。本番のレプリカで、頻出する重いクエリを対象に回してみることは可能だという意見もあった(直接の引用ではなく、コメントの要旨の要約、@dnautics)。
現実的な絵はこうだ。汎用のクエリプランナを言語モデルで置き換える未来を、この実験は描いていない。代わりに、定期実行される重い分析クエリの一覧をオフラインで探索し、実測で検証されたヒントを保存し、プランの変化を監視する「オフラインのプランチューナ」という狭い製品なら十分に描ける。実際Hacker Newsには、そういう製品はあるのかという質問も寄せられた(直接の引用ではなく、コメントの要旨の要約、@ashley95)。その製品の核となる競争力はモデルの大きさではなく、計測ハーネスの信頼性だろう。
結論
1.81倍という数字は嘘ではない。ただしそれは「4BモデルがPostgresより速いプランを出す」ではなく、「4Bモデルがクエリあたり最大15の候補を出し、その中から実際に実行して速かったものだけを選べば、メモリに載った8.5GBのIMDbにおけるJOBの113クエリで、クリッピングされた幾何平均1.81倍が得られる」という意味である。モデル自身の単独選択では1.40倍で、そのときは退行が7件あった。
この区別が重要なのはテールのためだ。クエリオプティマイザが人を叩き起こすのは、平均が1.4倍のときではなく、一つのクエリが20倍遅くなったときである。Baoが2020年にテール性能を学習型最適化の失敗要因に挙げたことも、今回の実験の退行0件が計測フィルタから来ていることも、同じことを語っている。安全性は生成器ではなく検証ループから来る。
あなたのデータベースで最もコストの高いクエリを10個思い浮かべてほしい。それらのプランが変わったとき、それを検知する仕組みはあるだろうか。ないのなら、どのプランナを使おうと、次の退行は平均の中に埋もれて届くことになる。
出典: