ようこそ、Cloud Spannerの世界へ。
「Cloud Spannerって、世界中のデータを一瞬で見つけ出す魔法のデータベースですよね?」と、よく若手のエンジニアから聞かれます。確かに魔法のように見えますが、その裏側には、驚くほど緻密で「賢い判断」を繰り返す頭脳が隠れているんです。
今日は、その頭脳の核となる「インデックス選択ロジック」についてお話ししましょう。
難しく聞こえるかもしれませんが、実は「巨大な図書館で、どうやって目当ての1冊を最短で見つけるか?」という日常的な判断と同じなんですよ。ここをクリアすれば、Cloud Spannerの基本はバッチリマスターできます。一緒に紐解いていきましょう。
—
1. なぜ「インデックス」が必要なの?
例えば、あなたが100万冊の本がある巨大な図書館にいると想像してください。
- 全件スキャン(フルスキャン): 端から1冊ずつタイトルを確認していく。
- インデックス(索引): 「著者名リスト」や「ジャンル別カード」を使って、場所を特定する。
当然、インデックスを使ったほうが早いですよね。でも、もし「赤い表紙の本を探して」と言われたらどうでしょう? 全体の9割が赤い本だったら、わざわざ索引を見るより、棚を端から見たほうが早いかもしれません。
Cloud Spannerは、クエリ(命令)を受け取った瞬間、「索引を使うべきか、それとも全部見たほうが早いか?」を瞬時に計算しています。これが「インデックス選択」の本質です。
2. Spannerの頭脳「コスト評価関数」の仕組み
Spannerがどの道を通るか決める時、「コスト評価関数」という数式を使います。これは、いわば「目的地までの移動時間とガソリン代の予測」のようなものです。
Spannerは以下の3つのポイントを天秤にかけています。
① 読み取る行数(データの絞り込み性能)
「東京都に住んでいる人」を探すのと、「東京都に住んでいて、1990年1月1日生まれの人」を探すのでは、後者の方が圧倒的に候補が絞れますよね。このように、どれだけ候補を減らせるかを「選択性(Selectivity)」と呼びます。
② データの「お引っ越し」が必要か(バックジョイン)
ここがSpannerの面白いところです。
「名前」だけ載っているインデックスを使って検索したのに、結果として「住所」も必要な場合、Spannerはインデックスを見た後に「住所が書いてある元のテーブル」までデータを取りに戻らなければなりません。
この「戻る作業(バックジョイン)」はコストが高い(時間がかかる)ため、Spannerは「これなら最初から元のテーブルを全部見たほうがマシかな?」と悩むわけです。
③ 統計情報(ライブラリの最新データ)
Spannerは常に「どのデータがどれくらい存在するか」の統計を取っています。
- 「苗字が『佐藤』さんは何人くらいいるか」
- 「注文日はどの日付に集中しているか」
こうした最新の統計データ(Statistics)を元に、コストを計算しています。
3. 具体的な例で見てみよう
例えば、ユーザー情報を管理するこんなテーブルがあるとします。
— ユーザーテーブル
CREATE TABLE Users (
UserId INT64 NOT NULL,
UserName STRING(MAX),
Country STRING(MAX),
LastLogin TIMESTAMP,
) PRIMARY KEY (UserId);
— 「国」で検索するためのインデックス
CREATE INDEX UsersByCountry ON Users(Country);
ここで、次のようなクエリを実行したとしましょう。
— 日本に住んでいるユーザーの名前を知りたい
SELECT UserName FROM Users WHERE Country = ‘Japan’;
この時、Spannerの頭脳(オプティマイザ)はこう考えます。
1. プランA(インデックス利用): `UsersByCountry` で ‘Japan’ の人を特定し、その後 `Users` テーブルに `UserName` を取りに行く。
2. プランB(フルスキャン): `Users` テーブルを最初から最後まで全部見て、’Japan’ の人を探す。
もし日本ユーザーが100人ならプランAを選びますが、ユーザーのほとんどが日本人なら「わざわざインデックスを見に行く手間がもったいない」と判断してプランBを選ぶこともあります。賢いでしょう?
4. Spannerをさらに賢く使う「プロの知恵」:STORING句
先ほどの「元のテーブルに取りに戻る手間(バックジョイン)」を失くすための、魔法の言葉があります。それが `STORING` です。
— UserNameもインデックスの中に「ついでに」保存しておく
CREATE INDEX UsersByCountry On Users(Country) STORING (UserName);
こうすると、インデックスを見るだけで `UserName` も手に入るので、元のテーブルを見に行く必要がなくなります。これを「カバリングインデックス」と呼びます。Spannerはこのルートが大好きで、迷わず最速の道を選んでくれます。
5. 実行計画(EXPLAIN)を覗いてみよう
自分の書いたクエリがどう判断されたかは、Google Cloud コンソールの「クエリ実行計画」で見ることができます。
- Index Scan: インデックスを使ってくれた!成功です。
- Distributed Cross Apply: これが出たら「元のテーブルに取りに戻る作業」が発生しています。
- Full Table Scan: インデックスが使われていません。データ量が多い場合は要注意です。
まとめ:Spannerとの信頼関係を築くために
Cloud Spannerのインデックス選択は、あてずっぽうではありません。「統計情報を元にした、冷徹かつ合理的なコスト計算」に基づいています。
もしSpannerが思った通りのインデックスを使ってくれない時は、「統計情報が古くなっていないかな?」「バックジョインのコストが高すぎてSpannerが遠慮しているのかな?」と、優しく寄り添ってあげてください。
ここをクリアすれば、Cloud Spannerの基本はバッチリマスターできますよ。
次は、さらに効率を上げるための「インデックスの設計指針」についてお話ししましょうか。一歩ずつ、伝説のエンジニアへの階段を登っていきましょう。応援しています!
コメント