Spannerオプティマイザの深淵:なぜ「魔法」は時に裏切るのか
Cloud Spannerを単なる「強力なRDBMS」と定義しているうちは、まだ真の力には到達していない。Spannerは分散環境における一貫性とスケーラビリティを極限まで追求した、世界でも類を見ない「分散型クエリ実行エンジン」である。
多くのエンジニアが「なぜオプティマイザはあのインデックスを選ばないのか?」という憤りを感じる。しかし、オプティマイザを非難する前に、我々はそれが何を考え、何に怯えているのかを理解しなければならない。
1. 統計情報の背後にある「分散」の現実
Spannerのクエリ・オプティマイザは、単なるコストベース・オプティマイザ(CBO)ではない。分散環境特有のコストを計算する必要がある。
- RPCオーバーヘッド: スプリット(データ分割)をまたぐ通信コスト。
- 計算の局所性: どのノードで結合(Join)を行うのが最もネットワーク負荷を抑えられるか。
- データ分布: `SPAN_STATS`によって保持される統計情報は、常に「最新の近似値」である。
オプティマイザがインデックスを無視する場合、それは「インデックススキャンによるランダムアクセス(シーク)コスト」と「フルスキャン後のシーケンシャルアクセスによるコスト」を天秤にかけ、前者が分散環境下で指数関数的に増大するリスクを感知しているからだ。
特に、`WHERE`句の選択性が低い(Cardinalityが低い)場合、オプティマイザは「インデックスを使うと、メインテーブルへのキー参照が膨大な回数発生し、ノード間通信でネットワークが飽和する」と判断する。この計算は驚くほど冷徹で、そしてしばしば我々の直感より正確だ。
2. インデックス強制指定(FORCE INDEX)の「禁忌」と「特効薬」
Spannerには `FORCE INDEX` という強力な道具がある。しかし、これを「クエリが遅いから」という理由だけで使うのは、外科手術のメスで薪を割るようなものだ。
FORCE INDEX を使用すべき唯一の条件
オプティマイザが「将来的なデータ増大」や「統計情報のラグ」を考慮しすぎて、現在の最適な実行計画を放棄しているとき。これ以外に妥当な理由はない。
— 悪い例:単に遅いからという理由で強制する
SELECT FROM Users@{FORCE_INDEX=UsersByEmail} WHERE Email = ‘…’
— 良い例:オプティマイザの判断をバイパスして、特定のアクセスパスを保証する
— 分散JOINのコスト見積もりが、実際のスプリット配置と乖離しているケース
SELECT /@ FORCE_INDEX=UsersByEmail / FROM Users WHERE Email = ‘…’
なぜ注意が必要なのか?
1. データ分布の変化: 今日の最適解は、明日の地獄になり得る。データが数テラバイトに増大し、スプリットが再配置(Split Rebalancing)された瞬間、強制されたインデックスが「全ノードへのブロードキャスト」を引き起こし、クラスタ全体を麻痺させる可能性がある。
2. 実行計画の硬直化: オプティマイザは「適応型」である。インデックスを強制すると、そのクエリは進化を止める。システムの成長に合わせてクエリも適応させる権利を、我々が奪ってしまうのだ。
3. チーフアーキテクトからの提言:インデックス設計の哲学
もし `FORCE INDEX` を検討するほど追い詰められているなら、それはインデックスの選択ではなく、「データモデルの欠陥」を疑うべきだ。
- STORING句の活用: インデックスに `STORING` 句で必要なカラムを含めよ。メインテーブルへのルックアップ(Key Lookup)を排除し、インデックスのみでクエリを完結させる「カバリングインデックス」こそが、Spannerにおける究極の高速化術だ。
- インターリーブ(Interleaving): 親子関係にあるテーブルを物理的に同じスプリットに配置せよ。これにより、分散結合をローカル結合へと昇華させ、オプティマイザがインデックスを選択しやすくする。
— インデックスにカラムを詰め込むことで、メインテーブルへの参照を回避する
CREATE INDEX UsersByEmail ON Users(Email) STORING (Name, CreatedAt);
結論:オプティマイザと対話せよ
Cloud Spannerのクエリ実行計画(`EXPLAIN ANALYZE`)を読み解くことは、データベースエンジンの思考を追体験することだ。
オプティマイザを信じすぎてもいけないが、無視してもいけない。彼らは、我々が指定したインデックスの制約の中で、ネットワークという名の巨大な迷路を最速で駆け抜けるルートを必死に探している。
`FORCE INDEX` は最後の切り札だ。それを使う前に、まず統計情報を更新し、インデックスのカバリングを最適化し、それでもなおエンジンが「迷っている」場合にのみ、そのメスを振るうがいい。
技術の深淵へようこそ。Spannerを使いこなすということは、分散システムの理(ことわり)と戦うことに他ならない。
コメント