Cloud Spannerの「インターリーブ」という劇薬:設計者が知るべき極限の真実
Cloud Spannerを触り始めて最初にぶつかる壁が「インターリーブ」だ。
「物理的にデータを隣接させてI/Oを高速化する」という謳い文句は魅力的だが、これを安易に使うと、数年後のシステム運用で必ず地獄を見る。
今日は、Spannerのアーキテクチャの根幹に関わるインターリーブについて、ドキュメントには書かれていない「実務上の境界線」と「設計の哲学」を叩き込む。
—
1. インターリーブの「物理的」本質を理解せよ
インターリーブとは、子テーブルの行を親テーブルの行と同じスプリット(物理ノード上のデータ断片)に配置する技術だ。
これにより、親子関係のJOINが「ネットワーク越しの通信」ではなく「ローカルメモリ上のポインタ参照」に近いコストで完結する。しかし、これを「JOINを避けるための魔法」だと勘違いしてはいけない。これはあくまで「物理的なデータ局所性の最適化」であり、データモデルの論理的な制約を強制する手段である。
2. インターリーブの設計制約:越えてはならない一線
① 深さの制限と「再帰のコスト」
インターリーブ階層は最大6階層までだ。しかし、現場の感覚で言えば「3階層」を超えた時点で設計を見直すべきだ。
なぜか?深い階層になればなるほど、インデックスの更新コストや、特定の親子関係に紐づくロックの粒度が複雑化し、ホットスポットの特定が困難になるからだ。
② 親削除時の破壊的影響:`ON DELETE CASCADE`
インターリーブされた子テーブルは、親が消えれば問答無用で消える。これはパフォーマンス的には最高だが、運用上のリスクが極めて高い。
例えば、`Users` -> `Orders` -> `OrderItems` とインターリーブしている場合、ユーザーを1人削除するだけで、関連する数万件の注文情報が瞬時に「物理消去」される。誤操作やバグによる全損のリスクと常に隣り合わせであることを忘れるな。
—
3. 実践的設計パターン:こう設計せよ
アンチパターン:何でもかんでもインターリーブする
「JOINが遅いから全部インターリーブにする」という考えは捨てろ。インターリーブは、「親のライフサイクルに完全に支配され、かつ頻繁に同時に読み込まれるデータ」にのみ適用する。
ベストプラクティス:適度な粒度での「疎結合」
例えば、ユーザー設定のようなメタデータであればインターリーブは有効だが、ログのような「無限に増え続けるデータ」をインターリーブしてはいけない。ログが肥大化すると、親テーブルの物理スプリットが巨大化し、スプリットの分割(Split)が頻発して、逆にパフォーマンスが不安定になる。
— 良い設計例: 頻繁にアクセスされるユーザー設定
CREATE TABLE Users (
UserId INT64 NOT NULL,
— …
) PRIMARY KEY (UserId);
CREATE TABLE UserSettings (
UserId INT64 NOT NULL,
SettingKey STRING(MAX),
SettingValue STRING(MAX),
) PRIMARY KEY (UserId, SettingKey),
INTERLEAVE IN PARENT Users ON DELETE CASCADE;
— 解説: UserSettingsはUserIdというキーで必ずアクセスされるため、
— このインターリーブは極めて高いパフォーマンスを発揮する。
—
4. パフォーマンスの落とし穴:見えないホットスポット
インターリーブの最大の罠は「書き込みの競合」だ。
親テーブルの特定の行に対して、複数の子が同時に書き込みを行おうとすると、親テーブルのロック(または特定の物理ノード上のロック)で競合が発生する。
- 対策:
- 子テーブルの主キーの先頭に、適度なランダム値(Shard ID)を付与して分散させる。
- インターリーブを適用する前に、そのデータが「単一の親に対して書き込みが集中する構造か」を必ずプロファイリングすること。
—
5. チーフアーキテクトからの提言
「インターリーブを使うべきか?」という問いに対する私の回答はいつも同じだ。
「そのデータモデルは、インターリーブなしでは許容できないほどレイテンシにシビアか?」と自分に問いかけろ。
Spannerのクエリエンジンは非常に優秀だ。インターリーブなしでも、適切なインデックスと統計情報があれば、多くのアプリケーションで十分な速度が出る。
インターリーブは、いわば「設計のカード」だ。むやみに切るな。本当に必要なとき、限界まで追い詰められたときのために温存しておけ。
設計レビューで「なぜインターリーブしたのか」を説明できない設計は、即座に却下する。それが、スケーラブルなシステムを生き残らせるための唯一の道だ。
—
今日の結論:
インターリーブは「物理的な特権」である。その特権を行使する代償として、システム全体の柔軟性と、物理的な運用負荷を背負う覚悟を持て。設計は常に「シンプルさ」と「スケーラビリティ」のトレードオフだ。それを忘れた時、エンジニアとしての成長は止まる。
コメント