0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PostGIS が提供する R-Tree ベースのインデックス

0
Last updated at Posted at 2026-04-16

以下を読みながら調べたことをまとめる。個人のメモです。

Postgres の標準の空間の演算子

まずそもそも大前提として、PostgreSQL本体には最初から幾何学データ型(Geometric Types)と、それらを操作するための演算子が組み込まれている。単純な平面座標(XY)としての計算であれば、標準機能だけで十分実用的である。

-- 1. テーブルの作成(標準の幾何学型を使用)
CREATE TABLE locations (
    id SERIAL PRIMARY KEY,
    name TEXT,
    pos POINT  -- 標準の点型 (x, y)
);

-- 2. データの挿入
-- 緯度経度を模した数値を入れることが可能
INSERT INTO locations (name, pos) VALUES 
('東京駅', '(139.767, 35.681)'),
('新宿駅', '(139.700, 35.689)'),
('渋谷駅', '(139.701, 35.658)');

-- 3. インデックスの作成(標準のGiSTが使用可能)
CREATE INDEX idx_locations_pos ON locations USING GIST (pos);

-- 4. 矩形範囲内にある地点を検索
-- 演算子「@>」は「左辺が右辺を包含するか」
-- box('(x1, y1), (x2, y2)') で範囲を指定
SELECT * FROM locations 
WHERE box('(139.70, 35.65), (139.71, 35.67)') @> pos;

-- 5. 指定した地点に近い順に並べる(KNN検索)
-- 演算子「<->」は2点間の距離を返す
SELECT name, pos <-> point(139.767, 35.681) AS distance
FROM locations
ORDER BY distance ASC
LIMIT 5;

-- 6. 円(半径)の中に入っているか判定
-- circle('<(x, y), radius>') で円を定義
SELECT * FROM locations
WHERE circle('<(139.70, 35.65), 0.05>') @> pos;

Postgres の標準インデックス型

さらに、PostgreSQLは、以下のインデックス型を標準提供している。

image.png

つまり、extension を使わずとも、R-Treeを内部アルゴリズムに用いる GiST インデックスを作ることは可能である。

-- 1. 点 (point)
-- 内部ロジック: R-Tree (2D MBR)
-- 用途: 単純なXY座標の管理
CREATE INDEX idx_std_point ON table_name USING GIST (pos);

-- 2. 矩形 (box)
-- 内部ロジック: R-Tree (2D MBR)
-- 用途: 範囲エリア、ウィンドウ検索
CREATE INDEX idx_std_box ON table_name USING GIST (area_box);

-- 3. 多角形 (polygon)
-- 内部ロジック: R-Tree (外接する矩形でフィルタリング)
-- 用途: 複雑な形状の境界
CREATE INDEX idx_std_poly ON table_name USING GIST (zone_poly);

-- 4. 円 (circle)
-- 内部ロジック: R-Tree (外接する矩形を使用)
CREATE INDEX idx_std_circle ON table_name USING GIST (radius_zone);

この GiST インデックスは、「多次元データ(空間データ)の包含関係や重なり」 を効率的に処理することができる。例えば、「ある特定の矩形(範囲)の中に含まれる地点を検索したり、複数の図形が重なっている部分を特定したりする場合」 に真価を発揮する。

しかしながら、もし R-Tree を利用したより複雑なクエリを使いたいのであれば、PostGIS extention を使えば良い。

PostGIS extention が提供するもの

1. カラム型

以下の型のカラムを作成できるようになる。

image.png

2. インデックス型

上記のカラム型を使って、以下のような応用的な GiST インデックスを作成できるようになる。
⚠️ USING 句で、カラムに入れるべき実データの型を明確にするために: geometry(*, 4326)という形で型を記しているが、実際には入れてはいけない。

CREATE EXTENSION postgis;

-- 1. 基本的な2次元平面図形
-- 内部ロジック: R-Tree (2D MBR)
CREATE INDEX idx_geom_2d ON table_name USING GIST (location: geometry(Point, 4326));
CREATE INDEX idx_area_2d ON table_name USING GIST (boundary: geometry(Polygon, 4326));

-- 2. Z軸(高さ)を含む3次元図形
-- 内部ロジック: R-Tree (3D MBR / 立体的な箱)
CREATE INDEX idx_geom_3d ON table_name USING GIST (location: geometry(PointZ, 4326));
CREATE INDEX idx_area_3d ON table_name USING GIST (building: geometry(PolygonZ, 4326));

-- 3. M値(計測値)を含む図形(路線のキロポストなど)
-- 内部ロジック: R-Tree (次元に応じた箱)
CREATE INDEX idx_route_m ON table_name USING GIST (track: geometry(LineStringM, 4326));
CREATE INDEX idx_full_4d ON table_name USING GIST (sample: geometry(PointZM, 4326));

-- 4. 地球儀ベースの地理座標(球面上)
-- 内部ロジック: R-Tree (Spherical MBR)
CREATE INDEX idx_geog_2d ON table_name USING GIST (location: geography(Point, 4326));

3. クエリの空間演算子

image.png

4. クエリの関数

image.png

これにより、以下のようなクエリを実行できるようになる。

-- 1. 空間関係の判定 (関係演算子)
-- インデックスを利用して「特定の範囲に含まれるか」を判定
SELECT name FROM stations 
WHERE ST_Intersects(geom, ST_GeomFromText('POLYGON((...))', 4326));

-- 2. 近傍検索 (KNN検索)
-- 特定の地点から近い順に5件取得 (GiSTによる高速化)
SELECT name, geom <-> ST_SetSRID(ST_Point(139.7, 35.6), 4326) AS dist
FROM stations 
ORDER BY dist ASC LIMIT 5;

-- 3. 半径検索 (指定距離以内)
-- 建物Aから半径500メートル以内にある施設を抽出
SELECT * FROM facilities 
WHERE ST_DWithin(geom, (SELECT geom FROM buildings WHERE id = 1), 500);

-- 4. 計測 (距離・面積)
-- 球面(geography)として、2点間の距離をメートル単位で取得
SELECT ST_Distance(geog1, geog2) FROM route_table;

-- 5. 形状の加工と生成
-- 特定の線から周囲10mのバッファ(面)を生成し、その面積を求める
SELECT ST_Area(ST_Buffer(geom, 10)) FROM roads WHERE id = 100;

-- 6. フォーマット変換
-- 内部型を Web アプリで扱いやすい GeoJSON 形式で出力
SELECT ST_AsGeoJSON(geom) FROM markers;

標準提供の R-tree アルゴリズムと PostGIS が提供する R-tree アルゴリズムの違い

以下の通り。

image.png
image.png

Appendix: そもそも R-Tree とは何か

以下の通り。(ref)

image.png

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?