【実務・中級編】 インデックスのバックフィルプロセス – Cloud Spanner

Cloud Spannerのインデックス・バックフィル:その「見えない代償」と賢明な設計戦略

現場のアーキテクトとして、多くのプロジェクトで「インデックスを後から追加する」という単純な操作が、本番環境で予期せぬレイテンシのスパイクやリソース枯渇を招く瞬間を何度も目撃してきた。

Cloud Spannerにおけるインデックス作成は、単なるDDLの実行ではない。それは、数億〜数千億行のデータをバックグラウンドで走査し、再構築を行う「分散バックフィル処理」そのものだ。この挙動を理解せずに運用することは、高速道路の真ん中で突然エンジンを載せ替えるようなものだ。

今回は、このバックフィル処理の深層と、エンジニアが知っておくべき「現場の知恵」を共有する。

—

1. バックフィルは「非同期の巨大な嵐」である

`ALTER TABLE … ADD INDEX` を実行した瞬間、Spannerの各スプリット(データ分割単位)では、既存データに対するインデックスエントリーの生成が開始される。

重要なのは、これが「非同期」であるという点だ。
DDLコマンド自体は即座に(あるいは短いロック時間で)成功したように見えるが、裏側では以下のプロセスが並行して走っている。

1. スキャンフェーズ: 全スプリットを走査し、新しいインデックス値を抽出。
2. 書き込みフェーズ: 抽出したデータを新しいインデックス用のテーブル(Spanner内部ではインデックスもテーブルの一種として管理される)に書き込む。

ここで陥る罠

バックフィル中、システムは既存のトランザクションを処理しつつ、裏で膨大なI/Oを消費する。大規模なデータセットに対してインデックスを追加すれば、当然ながらCPU使用率とディスクI/Oが跳ね上がる。「インデックス追加によるパフォーマンスの低下」は、Spanner運用における最大の「想定内」であるべきだ。

—

2. 進捗をどう「可視化」するか

Spannerは、インデックスのビルド状況を `INFORMATION_SCHEMA` を通じて公開している。勘に頼った運用はエンジニアの恥だ。以下のクエリで、現在の進捗を正確に把握せよ。

— 現在のインデックス構築状況を確認するためのクエリ
SELECT
TABLE_NAME,
INDEX_NAME,
INDEX_STATE
FROM INFORMATION_SCHEMA.INDEXES
WHERE INDEX_STATE = ‘BUILDING’;

— もっと詳細に知りたい場合(バックフィルの進行状況を確認)
SELECT
INDEX_NAME,
BACKFILL_PROGRESS
FROM INFORMATION_SCHEMA.INDEXES
WHERE TABLE_NAME = ‘YourTableName’;

`BACKFILL_PROGRESS` が 100 に達するまで、そのインデックスはクエリのオプティマイザには使用されない(`INDEX_STATE` が `READY` になる必要がある)。途中でクエリがインデックスを無視するのはバグではない。インデックスが完成するまでの「仕様」だ。

—

3. 実務で守るべき「堅牢な設計パターン」

インデックス追加による影響を最小化するための、私のチームで定めた鉄則を伝授する。

① トラフィックの谷間を狙え

オートスケーリングが効いているとはいえ、ピーク時のバックフィルは自殺行為だ。Cloud MonitoringでCPU使用率を監視し、グラフが最も穏やかな時間帯に実行する。

② 一括ではなく、段階的に

テーブルに複数のインデックスを追加したい場合、一度にDDLを流すのは避けるべきだ。 複数のバックフィルが同時に走ると、CPUリソースの競合が激化し、アプリケーション全体のレイテンシが予測不能になる。
「1つずつ追加し、`READY` 状態になるのを待ってから次へ進む」これがプロの流儀だ。

③ インデックスの「重さ」を見極める

以下のいずれかに該当する場合、特に慎重になれ。

  • 高カーディナリティ: インデックスエントリーが膨大になる。
  • 頻繁な更新: `STORING` 句で多くの列を含めている場合、書き込み負荷が倍増する。
  • 大規模テーブル: 数テラバイト級のテーブルでは、バックフィル完了までに数時間〜数日かかる可能性がある。

—

4. 結論:アーキテクトの視点

インデックスのバックフィルは、Spannerという分散データベースが持つ「データの一貫性を保ちながら、無停止でスキーマを進化させる」という強力な能力の裏返しだ。

もしあなたがDDLを発行する前に「この操作が今、クラスタにどれだけの負荷を与えるか?」を想像できているなら、あなたはもう一人前のSpannerエンジニアだ。

最後のアドバイス:
インデックスは「あればあるほど良い」というものではない。全てのインデックスは、書き込み処理のコストを食いつぶす「負債」になり得る。不要なインデックスは容赦なく削除し、本当に必要なクエリに対してのみ、計画的にバックフィルを走らせる。このバランス感覚こそが、堅牢なシステムを作る。

現場からは以上だ。コードレビューでまた会おう。

コメント

タイトルとURLをコピーしました