Cloud Spannerのオプティマイザを飼い慣らす:深淵なる実行計画制御の美学
Cloud Spannerを「ただの分散RDBMS」と呼ぶのは、エンジンの奥底に流れる分散トランザクションの鼓動を理解していない者の言葉だ。
我々がSpannerに対して発行するクエリは、単なるテキストではない。それは、数千台のノードが協調し、Paxosによって整合性が担保された広大なデータ空間に対する「命令」である。Spannerのクエリ・オプティマイザは非常に優秀だが、時として、データ分布の歪みや、クエリプランの「局所最適」に陥ることがある。
本稿では、オプティマイザが判断を誤った際、あるいは意図的な計算コストの削減を狙う際に用いる「ヒント句」の深淵に触れる。これは単なるチューニングではない。実行エンジンに対する直接的な介入である。
—
1. 物理プランナーの裏側を覗く
Spannerのクエリ・オプティマイザは、コストベース最適化(CBO)を採用している。しかし、分散環境特有の「ネットワークI/Oコスト」と「ノード内ローカル処理コスト」のトレードオフは、統計情報の鮮度やサンプリング誤差に強く依存する。
ヒント句を使用するということは、「統計情報を盲信するな、アーキテクチャの真実を見ろ」というエンジニアとしての意思表明だ。
2. FORCE_JOIN_ORDER:Nested Loopの呪縛からの解放
大規模なJOINにおいて、オプティマイザが稀に「Nested Loop Join」を深層で選択し、指数関数的なレイテンシ爆発を招くことがある。特に、左辺テーブル(Outer)のカーディナリティが小さいと判断された瞬間にこの現象が起きやすい。
— 明示的にJOIN順序を固定する
— 分散環境において、左辺テーブルの結果セットを各ノードへブロードキャストするコストを計算に入れる
SELECT
t1.id,
t2.val
FROM
TableA AS t1
INNER JOIN@{FORCE_JOIN_ORDER=TRUE}
TableB AS t2 ON t1.key = t2.key
WHERE
t1.status = ‘ACTIVE’;
極限の知見:
`FORCE_JOIN_ORDER`は、単に「順序を守る」以上の意味を持つ。これは「どちらのテーブルを駆動表(Driving Table)にするか」を決定づける行為だ。`TableA`がすでに特定のSplitに局所化されている場合、この強制介入によって、ネットワークを跨ぐシャッフルコストを劇的に抑え込める。
3. JOIN_METHOD:ハッシュか、それともマージか
`HASH JOIN`と`APPLY JOIN`(Nested Loop相当)の選択は、メモリ消費量とスループットの均衡点にある。
- HASH JOIN: メモリを大量に消費するが、スループットは高い。大規模なデータセットの突き合わせに最適。
- APPLY JOIN: メモリ消費は極小だが、右辺へのルックアップ回数が膨大になるとCPUを焼き切る。
— 巨大なデータセットを扱う場合、HASH JOINへの強制変更を検討する
SELECT
FROM Users@{JOIN_METHOD=HASH_JOIN} AS u
JOIN Orders AS o ON u.id = o.user_id;
アーキテクトの視点:
もしクエリが `Memory Limit Exceeded` で落ちているなら、それはオプティマイザが「ハッシュテーブルがメモリに収まる」と見積もったものの、実際には溢れたことを意味する。この場合、あえて`APPLY JOIN`に強制し、レイテンシを犠牲にしてでも安定性(メモリ消費の抑制)を優先する、あるいはサブクエリを分割して中間結果を物理テーブル化する戦略が正解だ。
4. 適用指針:介入すべきタイミング
ヒント句は「劇薬」である。以下の条件を満たさない限り、安易に使うべきではない。
1. 実行計画が「不安定」であること: クエリの実行時間が日によって変動する、あるいは統計情報の更新タイミングでプランが跳ねるケース。
2. データスキューが物理的に予測可能であること: 特定のキーにデータが偏っている場合、オプティマイザの統計情報は役に立たない。人間が「このデータは偏っている」と知っているなら、その直感をプランに埋め込むべきだ。
3. 計算量がシステム許容範囲を超えている: プロファイラ(`EXPLAIN ANALYZE`)で、特定の演算子にコストが集中していることを確認済みであること。
5. 最後に:伝説的エンジニアからの提言
Spannerにおいて、最も高価なリソースはCPUでもメモリでもない。「ネットワーク経由のデータシャッフル」だ。
ヒント句を使いこなすということは、データの流動を可視化し、システム内の物理的移動を最小化する設計に昇華させるということである。`FORCE_JOIN_ORDER`や`JOIN_METHOD`は、オプティマイザとの対話だ。彼らが「最善」だと思っている道が、必ずしも「最速」ではないということを、我々エンジニアは常に証明し続けなければならない。
謙虚に統計情報を読み、傲慢に実行計画を制御せよ。それがSpannerを支配する唯一の道だ。
コメント