TL

空間インデックス:R-Tree と Z-order/ヒルベルト曲線

緯度経度や矩形範囲の検索がなぜ B+Tree では遅いのか、その答えが原理から分かります。多次元を階層的に束ねる R-Tree と、一次元キーへ畳む空間充填曲線という二つの戦略を対比します。

応用空間インデックスR-Tree空間充填曲線ヒルベルト曲線インデックスデータベース最終更新: 2026-06-21
TL;DR要点だけ先に
  • 1.B+Tree は一次元の全順序が前提で、二次元の矩形範囲検索(窓問合せ)には素直に使えない。空間索引はこの「多次元には自然な全順序が無い」問題への二系統の答え。
  • 2.R-Tree は各エントリを最小外接矩形(MBR)で覆い、MBR を階層的に束ねる木。探索は問合せ矩形と重なる枝だけ降りる。鍵は分割時に MBR の重なりと無駄面積を最小化すること。
  • 3.Z-order・ヒルベルト曲線は空間充填曲線で多次元座標を一次元キーへ線形化し、既存の B+Tree にそのまま載せる。局所性を保つほど範囲検索が連続スキャンになり、ヒルベルトは Z-order より局所性が高い。

なぜ B+Tree では空間検索が破綻するのか

WHERE lat BETWEEN ... AND lon BETWEEN ... のような 矩形範囲検索(window query) や、「ある点から半径 5km 以内」を考えます。素朴に lat と lon それぞれへ B+Tree を張っても、うまくいきません。

理由は単純で、B+Tree は一次元の全順序(total order)を前提にしている からです。キーは数直線上に一列に並び、範囲検索は「葉リンクを連続して辿る」一回の連続スキャンになります。ところが二次元の点 (lat, lon) には、近さを保つ自然な一列の並びが存在しません。lat で並べれば lon が散らばり、lon で並べれば lat が散らばります。

その結果、lat の索引だけ使うと「緯度は範囲内だが経度は遠い」点まで大量に拾い、フィルタで捨てる羽目になります。二つの索引の結果を突き合わせる(ビットマップ AND)にしても、片側の候補が膨らめば効果は薄い。多次元には「近いもの同士が必ず隣り合う一列」が無い ——これが空間索引が解くべき本質的な問題です。

これに対する答えは大きく二系統あります。多次元のまま階層的に空間を束ねる R-Tree と、多次元を一次元キーへ線形化して既存の B+Tree に載せる空間充填曲線 です。前者は専用構造を作り、後者は既存の索引基盤を流用します。

観点R-Tree(専用木)空間充填曲線(線形化)
基本発想矩形を矩形で覆い階層的に束ねる多次元座標を一次元キーへ写して並べる
必要な索引基盤R-Tree 専用の実装が要る既存の B+Tree をそのまま使える
扱える形状点・矩形・線・多角形の MBR主に点(範囲はキー区間へ分解)
弱点重なり次第で枝を多く辿る曲線が空間的近傍を完全には保てない

R-Tree:最小外接矩形を階層的に束ねる

R-Tree は B+Tree を多次元へ一般化した平衡木です。葉に格納するのは個々の空間オブジェクトを覆う 最小外接矩形(MBR: Minimum Bounding Rectangle) で、内部ノードはその子たちの MBR をさらに覆う一回り大きな MBR を持ちます。つまり「矩形を矩形で包む」入れ子になっています。

  • 葉ノード:実オブジェクト(点・線・多角形)の MBR とその参照。
  • 内部ノード:子ノード全体を覆う MBR と子へのポインタ。
  • B+Tree と同様、全葉が同じ深さにある平衡木で、ノードは1ページに対応する。

探索(窓問合せ)はこう進みます。ルートから始め、各エントリの MBR が 問合せ矩形と重なる枝だけ を再帰的に降ります。重ならない枝は、その配下に答えが無いと確定するので丸ごと枝刈りできます。

R-Tree 窓問合せ search(node, Q):
  for each entry e in node:
      if MBR(e) が Q と重なる:        # 重ならなければ枝刈り
          if node が葉:  e を結果候補へ
          else:          search(child(e), Q)   # 重なる枝だけ降りる

ここに B+Tree との決定的な違いがあります。一次元の B+Tree では区切りキーが空間を 互いに素な区間 に分けるため、降りる枝は常に一本でした。R-Tree の MBR は 互いに重なってよい ので、問合せ矩形が複数の子 MBR にまたがると、複数の枝を同時に降りることがあります。重なりが多いほど辿る枝が増え、探索が劣化します。MBR の重なり(overlap)と無駄面積をいかに小さく保つかが R-Tree 性能の核心 です。

MBR は近似、答えは二段構え

MBR はあくまでオブジェクトの外接矩形であり、複雑な多角形そのものではありません。そのため R-Tree の探索は二段階になります。まず MBR の重なりで候補を絞る フィルタ段階、次に候補の実形状で厳密に判定する リファイン段階 です。フィルタは安価な矩形交差で偽陽性込みの候補を高速に出し、高価な厳密判定は候補だけに限定する——という役割分担で、空間索引は重い幾何計算を最小化します。

分割戦略:R-Tree の品質を決めるもの

ノードが満杯になったときの 分割(split) こそ、R-Tree の良し悪しを決めます。同じ点群でも、分割の仕方で MBR の重なりと総面積が大きく変わるからです。代表的な戦略を対比します。

分割戦略やることねらい / 代償
Guttman 二次法覆う面積の無駄が最大の2件を種にし、面積増が少ない側へ各件を割り振る実装が軽い/局所最適に陥りやすい
R*-Tree面積に加え重なり・周長・中心ズレも最小化し、満杯時に一部を再挿入(forced reinsert)重なりが大幅減で探索が速い/挿入が重い
STR 一括ロード全データを並べ替えてタイル状に詰め、下から木を組む(bulk load)静的データで隙間なく高品質/逐次更新向きでない

実務で広く使われるのは R*-Tree です。分割と挿入時に「子 MBR 同士の重なり」と「外接矩形の周長」まで評価関数に入れ、満杯ノードの一部エントリを抜いて挿し直す 強制再挿入 で木全体を整えます。結果として重なりが減り、窓問合せで降りる枝が少なくなります。代償は挿入コストの増大で、これは B+Tree のフィルファクタ と同様、更新負荷と探索効率のトレードオフです。

一方、初期構築時に全データが揃っているなら STR(Sort-Tile-Recursive)一括ロード が強力です。データを一方の軸でソートして縦帯(タイル)に切り、各帯内をもう一方の軸でソートしてページに詰め、それを下から束ねます。隙間なく詰まり重なりも小さい木が一度にできるため、逐次挿入より高品質かつ高速に構築できます。

重なりが大きい R-Tree は「全枝降り」に堕ちる

子 MBR が大きく重なり合うと、ほとんどの問合せが複数枝を降り、最悪では木の枝刈りがほぼ効かず全葉走査に近づきます。データが密で偏りが大きいほどこの傾向が出るため、更新主体なら R*-Tree、静的なら STR 一括ロードを選ぶのが定石です。空間索引の性能劣化を疑うときは、まず「子 MBR の重なり率」を見るのが筋です。

空間充填曲線:多次元を一次元キーへ線形化する

もう一方の戦略は、専用木を作らず 多次元座標を一次元の整数キーへ写す ものです。この写像に使うのが 空間充填曲線(space-filling curve) で、二次元(以上)の格子を一本の連続した線で隙間なく塗り潰す順序を与えます。各セルにその線上の通過順(曲線距離)を番号として振れば、(lat, lon) が一つの整数キーになり、あとは 既存の B+Tree にそのまま載せられます。専用実装が不要なのが最大の利点です。

良い曲線の条件は 空間的局所性の保存 です。空間で近い二点が、一次元キーでも近い値になってほしい。そうであれば、矩形範囲は「キーのいくつかの連続区間」に対応し、B+Tree の連続スキャンで読めます。局所性が崩れるほど、一つの矩形が多数の細切れキー区間に散らばり、ランダムアクセスが増えます。

Z-order(モートン順序)

Z-order 曲線 は最も実装が軽い線形化で、座標ビットを インターリーブ(交互配置) するだけで一次元キー(モートンコード)が得られます。

Z-order(モートン)コードの作り方(2次元)
  x = b2 b1 b0   y = a2 a1 a0  (各座標を整数ビット列に)
  モートンコード = a2 b2 a1 b1 a0 b0   ← y,x のビットを交互に並べる
  例) x=3(011), y=5(101) → 10 01 11 (2進) = 39

ビット演算だけで双方向に変換でき、四分木のセル番号とも自然に対応するため、実装が極めて簡単です。難点は 局所性の不連続 にあります。曲線が空間を Z 字に塗るため、隣接セルでもブロック境界をまたぐとキーが大きく飛ぶ「長いジャンプ」が生じます。このため一つの矩形が複数のキー区間に割れ、各区間を別々にスキャンする必要が出ます。

ヒルベルト曲線

ヒルベルト曲線 は、常に一つ前のセルと 隣接するセルへ進む(曲線が飛ばない)ように空間を再帰的に塗ります。Z-order のような長いジャンプが原理的に起きないため、空間的局所性が Z-order より高い のが定量的に知られた性質です。同じ矩形を覆うのに必要なキー区間の数が少なく断片化しにくいので、範囲検索がより連続的なスキャンになります。

代償は変換コストです。ヒルベルト座標の符号化・復号は、各ビット段で象限ごとに座標軸を回転・反転させる必要があり、ビットを混ぜるだけの Z-order より計算が重くなります。実装の軽さの Z-order、局所性の高さのヒルベルト という対比です。

観点Z-order(モートン)ヒルベルト曲線
キー生成座標ビットのインターリーブのみ象限ごとの回転・反転を伴う再帰変換
局所性(近傍保存)中(ブロック境界で長くジャンプ)高(常に隣接セルへ進み飛ばない)
矩形のキー区間断片化しやすい(区間数が多い)断片化しにくい(区間数が少ない)
変換コスト軽い(ビット演算)重い(段ごとの座標変換)
線形化は範囲検索を「区間集合」へ分解する必要がある

曲線キーで矩形検索するには、問合せ矩形を覆う一次元キーの 連続区間の集合(range decomposition) を求め、各区間を B+Tree でスキャンします。曲線の局所性が低いほどこの区間数が増え、偽陽性(矩形外なのに区間に含まれるセル)も増えてフィルタ負荷が上がります。ヒルベルトが好まれるのは、まさにこの区間数と偽陽性を抑えられるからです。なお点の等値・近傍検索は単純ですが、線形化は本質的に点向きで、面積を持つ多角形そのものの索引には R-Tree のほうが素直です。

二系統の使い分け

観点R-Tree(R*-Tree 等)空間充填曲線+B+Tree
索引基盤専用の空間索引実装が必要既存の B+Tree を流用できる
対象オブジェクト点・線・多角形(MBR で覆える形状全般)主に点(範囲はキー区間へ分解)
更新適性逐次挿入・削除に強い(平衡木)キー再計算で B+Tree に挿すだけで容易
性能の鍵MBR の重なり・無駄面積の最小化曲線の局所性と区間分解の質
代表実装PostGIS / Oracle Spatial / SQLite R*Tree分散 KVS・列指向のクラスタリングキー

選択の軸は明快です。多角形や線分など面積を持つ形状を厳密に索引したい、逐次更新が多いなら R-Tree(実装としては R*-Tree)。点データが中心で、既に B+Tree やソートキーの基盤がある/専用索引を持ち込めないなら空間充填曲線が向きます。後者は分散環境とも相性が良く、Z-order やヒルベルトでキーを作れば、近い点が同じパーティションやページに集まり、データ局所性をそのまま得られます。次元数が数十以上に上がると両者とも次元の呪いで劣化し、そこからは別系統の 近似最近傍索引(HNSW/IVF-PQ) の領分になります。

試験・面接で問われる要点

多次元には自然な全順序が無いため一次元 B+Tree では矩形検索が非効率、という出発点。R-Tree は MBR を階層的に束ね、問合せ矩形と重なる枝だけ降りること、MBR の重なり最小化が分割戦略(Guttman / R*-Tree / STR)の目的であること。空間充填曲線は多次元を一次元キーへ線形化し既存 B+Tree に載せること、ヒルベルトは飛ばないので Z-order より局所性が高いが変換は重い、という対比を説明できるように。

まとめ

まとめ

空間索引が解くのは「多次元には近さを保つ全順序が無い」問題です。一次元前提の B+Tree は矩形範囲検索に素直に使えません。R-Tree は各オブジェクトを最小外接矩形(MBR)で覆い、MBR を階層的に束ねた平衡木で、問合せ矩形と重なる枝だけを降ります。MBR は重なってよいぶん枝刈りが甘くなりうるので、重なりと無駄面積を最小化する分割戦略(Guttman 二次法・R*-Tree・STR 一括ロード) が性能の鍵で、探索は MBR フィルタと厳密リファインの二段構えです。もう一方の 空間充填曲線(Z-order・ヒルベルト)は多次元座標を一次元キーへ線形化し、既存の B+Tree にそのまま載せます。局所性が高いほど矩形が少ない連続区間に収まり、ヒルベルトは飛ばないので Z-order より局所性が高い代わりに変換が重い、という対比です。面積を持つ形状・逐次更新なら R-Tree、点データで既存索引を流用するなら空間充填曲線、というのが基本の使い分けで、データを区画へ束ねる発想は パーティショニング とも地続きです。

データベース Article

空間インデックス:R-Tree と Z-order/ヒルベルト曲線を実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

空間インデックス

比較で見る軸

難易度: advanced / カテゴリ: データベース / タグ数: 6

導入後に効く点

R-Tree は各エントリを最小外接矩形(MBR)で覆い、MBR を階層的に束ねる木。探索は問合せ矩形と重なる枝だけ降りる。鍵は分割時に MBR の重なりと無駄面積を最小化すること。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
advanced
カテゴリ
データベース
タグ数
6

判断チェックリスト

  • 自社の用途が「空間インデックス / R-Tree」に近いか確認する。
  • 強みである「B+Tree は一次元の全順序が前提で、二次元の矩形範囲検索(窓問合せ)には素直に使えない。空間索引はこの「多次元には自然な全順序が無い」問題への二系統の答え。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

空間インデックスR-Tree空間充填曲線ヒルベルト曲線インデックス空間インデックスR-Tree空間充填曲線