#概要
国土数値情報の森林地域や都道府県ポリゴンなどノード数の多いポリゴンとIntersectsしたい場合そのままやってしまうと遅いのですが、ST_Subdivide関数を使えばIntersectsを高速にできます。
ただ、Intersectsしたい地物が少ない・小さい場合などはST_Subdivideを実行する時間もかかるため、そのままIntersectsした方がいい場合もあります。
#ST_Subdivide関数について
指定した数より多いノードを持たないポリゴンを返します。
例として東京都の森林地域を下記のコードでST_Subdivideした場合は
(256個以下のノードに切り分ける)
SELECT
ST_Subdivide(geom,256)
FROM
japan_forest_pl;
結果としてはこのような状態で返ってきます。
この状態からST_Unionをすれば元のポリゴンへ戻すことが可能です。
#速度比較
例として、
日本全国の森林地域が格納されているjapan_forest_plテーブルと
日本全国の行政区域が格納されているjapan_city_plテーブルを
Intersectsさせて松山市の森林地域を抜き出したいと思います。
ポリゴンは全て国土数値情報のものを使用しています。
##そのままIntersectsを行う場合
SELECT
ST_Union(
ST_Intersection(forest_pl.geom,city_pl.geom)
) as geom
FROM
(
SELECT geom as geom
FROM japan_forest_pl
WHERE pref_code = '38'
) AS forest_pl,
(
SELECT geom as geom
FROM japan_city_pl
WHERE city_code = '38201'
) AS city_pl
WHERE st_intersects(forest_pl.geom,city_pl.geom)
Execution time: 23361.740 ms
#ST_Subdivide後のポリゴンをIntersects
SELECT
ST_Union(
ST_Intersection(forest_pl.geom,city_pl.geom)
) as geom
FROM
(
SELECT geom as geom
FROM japan_forest_pl_subdivide
WHERE pref_code = '38'
) AS forest_pl,
(
SELECT geom as geom
FROM japan_city_pl_subdivide
WHERE city_code = '38201'
) AS city_pl
WHERE st_intersects(forest_pl.geom,city_pl.geom)
Execution time: 13910.946 ms
10秒程度削減できました。
ただ、概要にもかきましたが1行政だとST_Subdivideの実行する時間を考慮するとそのまま実行する方が早いですね。
#おまけ
PostgreSQL9.5
Postgis2.3.7
だとバグが発生してたみたいです
追記(2019/9/28)
色々見てると2.5.0まで色々のバグが治ったりできたりしている関数みたいですね。
リングがない地物ではこの現象は発生していないのでリングがない地物で行うと良いかと思います。
ST_Subdivide(geometry,256)
before
after(ST_Union後の画像しか残ってなかった)
おそろしや・・・