【実務・中級編】 テーブル設計とスキーマ定義 – Cloud Spanner

Cloud Spannerの魂は「スキーマ」に宿る:伝説的アーキテクトが説くテーブル設計の極意

Cloud Spannerを「ただの分散RDB」だと思っているなら、今すぐその認識を捨てろ。これは、地球規模のスケールと厳密な一貫性を両立させるために、物理レイヤーの制約を極限まで抽象化した「エンジニアリングの芸術品」だ。

多くのプロジェクトがSpanner導入後にパフォーマンス劣化やホットスポットに苦しむ理由はただ一つ。「Spannerのアーキテクチャを理解せず、従来のMySQLやPostgreSQLの感覚で設計しているから」だ。

今回は、Spannerという怪物と共存し、極限のパフォーマンスを引き出すためのスキーマ設計の真髄を伝授する。

—

1. Primary Keyは「物理配置」そのものである

Spannerにおいて、`PRIMARY KEY`は単なる一意制約ではない。データがどのスプリット(ノード上のデータ単位)に配置されるかを決定する唯一の指針だ。

罠:単調増加するキーを避けるべけし

`INT64`のIDを`AUTO_INCREMENT`で付与する設計は、Spannerではアンチパターンの筆頭だ。
挿入がすべて末尾のノードに集中し、書き込みの「ホットスポット」が生まれる。分散DBの恩恵を自らドブに捨てる行為だ。

解決策:

  • UUID (v4): ランダムな値をキーにすることで、書き込みを全ノードへ均等に分散させる。
  • ビット反転: 既存のシーケンシャルなIDを使う必要があるなら、ビットを反転させて先頭ビットを分散させる。

— 良い設計例:UUIDを文字列ではなくBYTES(16)で持つ
— STRING(36)よりも容量効率が良く、インデックスのサイズも抑えられる
CREATE TABLE Users (
UserId BYTES(16) NOT NULL,
UserName STRING(256),
CreatedAt TIMESTAMP OPTIONS (allow_commit_timestamp = true),
) PRIMARY KEY (UserId);

—

2. データ型の選択:その1ビットがミリ秒を変える

Spannerの型選択は、単なる「型の適合」ではない。ストレージコストとCPU負荷の最適化だ。

  • NUMERIC vs FLOAT64: 金額計算で`FLOAT64`を使うエンジニアは、即座にレビューで差し戻す。小数点以下の微細な誤差が、監査で致命的な問題になる。正確性が求められる値には必ず`NUMERIC`を使え。
  • ARRAY型の活用: 1対多の親子関係がある際、JOINを避けるために「子要素をARRAYで親テーブルに持つ」のは極めて強力な最適化だ。ただし、ARRAYが数千要素を超えると行サイズ制限に抵触するため、適度な粒度を保て。
  • JSON型: 柔軟性は高いが、クエリの複雑化を招く。スキーマレスなデータが「本当に必要なのか」を自問自答せよ。構造が安定しているなら、迷わずカラムを切るべきだ。

—

3. 「インターリーブ(Interleave)」という最強の武器

Spanner特有の機能である`INTERLEAVE IN PARENT`を使いこなせているか?

これは、子テーブルのデータを親テーブルの物理的な近くに配置する仕組みだ。`Parent(OrderId)`と`Child(LineItemId)`をインターリーブすれば、親子のJOINは「同一ノード内のローカル参照」に昇格する。ネットワーク越しのデータ転送が消滅するのだ。

— 注文明細を注文テーブルと物理的に密着させる
CREATE TABLE Orders (
OrderId INT64 NOT NULL,
…
) PRIMARY KEY (OrderId);

CREATE TABLE OrderItems (
OrderId INT64 NOT NULL,
ItemId INT64 NOT NULL,
…
) PRIMARY KEY (OrderId, ItemId),
INTERLEAVE IN PARENT Orders ON DELETE CASCADE;

注意点: 親のデータが削除された際、子のデータも自動で消える(ON DELETE CASCADE)。この挙動を理解せずに使うのは危険だ。しかし、これを使うだけでJOINの速度は劇的に変わる。

—

4. スキーマ更新は「慎重に、かつ自動化せよ」

Spannerのスキーマ更新はオンラインで行われるが、大規模テーブルでの`ALTER TABLE`はバックグラウンドでリソースを消費する。

  • インデックスの追加は非同期: インデックスを作成しても、すぐにはクエリで利用されない場合がある。`BACKFILL`が完了するまで待つという「時間軸」を意識せよ。
  • マイグレーション管理: 手動のSQL実行は禁止だ。TerraformやSpanner専用のマイグレーションツールを使い、バージョン管理された状態を正とせよ。

—

最後に:アーキテクトからの助言

Spannerは、ただの「便利なデータベース」ではない。インフラの制約をエンジニアの設計力で突破するための「チェスボード」だ。

1. 物理的配置を想像せよ(Primary Key)。
2. JOINを最小化せよ(Interleave)。
3. 型には誠実であれ(NUMERIC, BYTES)。

これらの設計原則は、一度システムが巨大化した後では修正コストが天文学的になる。最初の一行の`CREATE TABLE`を書くその瞬間から、あなたはSpannerという巨獣を御するアーキテクトなのだ。

さあ、コードを開け。あなたの設計は、100年先まで耐えられるか?

コメント

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