【テクニカル・上級編】 NULLフィルタリングインデックス – Cloud Spanner

Cloud Spannerの深淵:NULL_FILTEREDインデックスがもたらす物理層の最適化

大規模分散データベースにおいて、インデックスは諸刃の剣だ。クエリの高速化という恩恵と引き換えに、書き込み時のオーバーヘッド、ストレージ容量の増大、そして何より「メモリレイヤへの負荷」というコストを支払わねばならない。

Cloud Spannerにおいて、`NULL_FILTERED`オプションを使いこなすことは、単なる節約術ではない。これはストレージエンジン層のデータ局所性を制御し、B-tree(Spannerにおける内部構造であるLSMライクな構造)の効率を極限まで高めるための「設計思想」だ。

今回は、この小さなオプションが、いかにして大規模データセットの物理的パフォーマンスを劇的に変容させるのか、その深層を紐解こう。

—

1. 物理ストレージの「ノイズ」を排除する

Spannerのインデックスは、それ自体が独立したキー空間を持つ独立したテーブルだ。もし、あるカラムにおいてデータの9割が`NULL`である場合、通常のインデックスを作成すると、その9割の行に対して「`NULL`である」というメタデータ(またはキー値)を永続化し、キャッシュに乗せることになる。

これはメモリの無駄遣いであると同時に、スキャン時の「シークノイズ」となる。

`NULL_FILTERED`を付与すると、Spannerのストレージエンジンは、そのカラムが`NULL`である行をインデックスのキー空間から完全に排除する。これは単に「行を省く」というレベルの話ではない。インデックスのリーフノードにおける論理構造から当該エントリを抹消し、インデックスサイズを物理的に縮小させることを意味する。

なぜこれが「伝説的」な最適化なのか

  • キャッシュ効率の最大化: インデックスが小さくなれば、同一メモリ量でより多くの「実効的なキー」をキャッシュできる。
  • 圧縮効率の向上: SpannerはSSTableに格納する際、連続するデータに対して圧縮をかける。`NULL`という「意味のない情報」が排除されることで、データブロック内のエントロピーが下がり、圧縮アルゴリズムがより高い効率を発揮するようになる。
  • 書き込みレイテンシの改善: インデックス更新時の不必要なIOを抑制できるため、高負荷なトランザクションにおけるP99レイテンシが安定する。

—

2. 実践:NULL_FILTEREDによるインデックス定義

例えば、非常に大規模なユーザーテーブルにおいて、`deleted_at`(削除日時)カラムを持つ場合を想定しよう。アクティブなユーザーのみを検索対象とするケースがほとんどであれば、以下のように定義する。

— 削除されていないユーザー(deleted_at IS NULL)のみを対象としたインデックス
— NULL_FILTEREDにより、削除済みユーザー(NULLではない値)のみがインデックスに含まれる
CREATE INDEX UsersByDeletedAt
ON Users (deleted_at)
NULL_FILTERED;

— 検索時には以下のようにクエリを投げる
— オプティマイザはNULL_FILTEREDインデックスを認識し、NULLの行を完全に無視する
SELECT UserID FROM Users WHERE deleted_at IS NULL;

※注:ここで重要なのは、`NULL_FILTERED`インデックスは「`NULL`値そのものを検索できない」という制約を内包している点だ。これは「クエリの要件をインデックス定義で強制する」という、堅牢なシステム設計における一つの契約(Contract)である。

—

3. チーフアーキテクトの視点:メモリレイヤへの負荷軽減

エンジニアの多くはインデックスのサイズを「ディスク容量」でしか測らない。しかし、Spannerの真のボトルネックは「インデックスがメモリに乗っているか否か」だ。

`NULL_FILTERED`を適用し、インデックスのフットプリントを数GB削減できたとしよう。この削減分は、そのまま「より重要な、頻繁に参照されるキー」をキャッシュするためのスロットとして解放される。

特に、以下のようなケースでは、`NULL_FILTERED`の有無がシステムのスループットに直結する。

1. オプション属性の疎なインデックス: 多くの行で値が空であるカラムに対するインデックス。
2. 論理削除フラグ: 削除済みフラグなどが大量に含まれるインデックス。
3. 一時的な状態フラグ: 処理待ち状態のレコードのみをインデックスし、処理済み(NULLや定数)を除外する場合。

—

4. 結び:設計に妥協を持ち込むな

Cloud Spannerは、単に「動けばいい」データベースではない。物理レイヤの特性を理解し、その挙動をコントロールする者にだけ、究極のパフォーマンスという果実を与える。

`NULL_FILTERED`は小さな機能だが、これを選択することは、「自分のデータセットの統計的な分布を完全に掌握している」という宣言に他ならない。

インデックス設計は、単なるクエリの高速化ツールではない。それはシステムのメモリ管理、IO管理、そしてスケーラビリティを統括するアーキテクチャそのものだ。

今日から、インデックス定義を眺めてみてほしい。「本当にこの`NULL`はインデックスに含まれるべきか?」と自問自答すること。その問いが、あなたのシステムを次のレベルへと押し上げる。

—
「データベースは、設定した通りにしか動かない。そして、設計した通りにしか速くならない。」

コメント

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