GIS開発研究所 > PostGISのST_Intersectsが遅い原因|GiSTインデックスの確認
2026年7月29日
•約6分で読めます
PostGISのST_Intersectsが遅いときに、GiST空間インデックス、実行計画、SRID、巨大ポリゴン、事前絞り込みを順番に確認する方法を解説します。EXPLAIN ANALYZEの読み方と、本番で性能劣化を再発させない監視項目をSQL例付きで紹介します。
PostGISでポイントと行政区域を重ねたり、設備が対象エリア内にあるか判定したりするとき、よく使うのがST_Intersectsです。数千件では問題なかったSQLが、数十万件に増えた途端に何分もかかることがあります。
そんなときは、SQLを複雑に書き換える前に、空間インデックスがあり、実際の検索で使われているかを確認しましょう。
次の順番で切り分けると、原因を見つけやすくなります。
EXPLAIN (ANALYZE, BUFFERS)でインデックスが使われているかPostGIS公式では、空間検索を速くするにはGiSTインデックスを作り、インデックス対応の空間関数を使う必要があると説明されています。ST_Intersectsはインデックス対応関数の1つです。
まず、対象テーブルのインデックスを確認します。
SELECT
indexname,
indexdef
FROM pg_indexes
WHERE schemaname = 'public'
AND tablename = 'assets';
geometry列geomにGiSTインデックスがなければ、次のように作成します。
CREATE INDEX CONCURRENTLY assets_geom_gix
ON public.assets
USING GIST (geom);
CONCURRENTLYを使うと、通常のインデックス作成より書き込みを止めにくくできます。ただし、トランザクション内では実行できず、処理時間も長くなることがあります。本番ではデータ量と実行時間を確認してください。
作成後は統計情報を更新します。
ANALYZE public.assets;
インデックスがあっても、検索条件やデータ分布によって使われない場合があります。実際のSQLにEXPLAINを付けます。
EXPLAIN (ANALYZE, BUFFERS)
SELECT a.id
FROM assets a
JOIN management_areas m
ON ST_Intersects(a.geom, m.geom)
WHERE m.id = 10;
実行計画で確認したい言葉は次のとおりです。
Index ScanやBitmap Index ScanがあるかSeq Scanで全件を読んでいないか小さなテーブルでは、インデックスより全件走査の方が速いと判断されることもあります。Seq Scanが出ただけで異常と決めつけず、実行時間と行数を一緒に見ましょう。
空間検索の対象が全年度・全地域に広がっていると、不要な比較が増えます。業務上の条件を先に入れます。
SELECT a.id
FROM assets a
JOIN management_areas m
ON ST_Intersects(a.geom, m.geom)
WHERE m.id = 10
AND a.status = 'active'
AND a.surveyed_at >= DATE '2026-01-01';
statusやsurveyed_atにも検索が多いなら、通常のB-treeインデックスを検討します。
CREATE INDEX CONCURRENTLY assets_status_surveyed_at_idx
ON assets (status, surveyed_at);
ただし、インデックスを増やしすぎると更新処理が重くなります。実際に使う検索条件へ絞りましょう。
比較する2つのレイヤーでSRIDが異なると、そのままでは空間演算できません。列定義とデータを確認します。
SELECT
ST_SRID(geom) AS srid,
GeometryType(geom) AS geometry_type,
count(*)
FROM assets
GROUP BY ST_SRID(geom), GeometryType(geom);
検索のたびにST_Transformをかけると、条件によっては列側のインデックスを使いにくくなります。よく使う座標系に保存時点で統一するか、変換後geometryへ式インデックスを作る方法を検討します。
頂点数が非常に多い都道府県境界、海岸線、管理区域などは、候補が絞られた後の厳密判定にも時間がかかります。
まず頂点数を確認します。
SELECT
id,
ST_NPoints(geom) AS point_count
FROM management_areas
ORDER BY point_count DESC
LIMIT 20;
用途によっては、表示用に簡略化したgeometryを別に持つ、またはST_Subdivideで分割した検索用テーブルを用意します。原本geometryを直接上書きせず、検索用データとして分けると安全です。
&&だけに置き換える&&は外接矩形が重なるかを調べるため、厳密な交差判定とは結果が異なります。候補抽出には使えますが、業務判定にはST_Intersectsなどの正確な条件が必要です。
SRIDの不一致を隠せても、毎回の座標変換が負担になります。入力時のSRID、保存するSRID、表示時のSRIDを整理しましょう。
VACUUM FULLはテーブルを書き換え、強いロックが発生します。まず通常のVACUUM (ANALYZE)、統計、インデックス、SQLを確認します。
データは毎月増えるため、改善時点の実行時間だけで終わらせないことが大切です。
ANALYZEを実行するpg_stat_statementsで確認するST_Intersectsの性能は、関数だけではなく、インデックス、データ量、ポリゴンの複雑さ、絞り込み条件で決まります。
PostGISの空間検索や大規模GISデータの性能改善でお困りの場合は、GIS開発を無料相談する。
千葉県出身。10歳の頃からプログラミングを始め、ゲーム、Webサイト、ロボット、スマホアプリなどを制作。大阪大学基礎工学部情報科学科で情報工学と統計学を学び、大学時代はAIを研究。大学在学中にWeb広告代理店でのインターンや人材系Webサービスの立ち上げを経験し、卒業後はフリーランスエンジニアとしてGISシステム、データ基盤構築、Webシステムの開発に従事。10年以上のWebアプリ開発・データ分析経験を基に、2023年9月に株式会社ビットライトを設立し、現場業務の仕組み化からデータ基盤構築、データ活用支援までを一気通貫で支援。