Skip to main content
added 38 characters in body
Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57

Always post the full EXPLAIN ANALYZE output here - some of us know how to make sense of it and may be able to help you even more!

Always post the full EXPLAIN ANALYZE output here - some of us know how to make sense of it!

Always post the full EXPLAIN ANALYZE output here - some of us know how to make sense of it and may be able to help you even more!

Source Link
geozelot
  • 30.9k
  • 4
  • 34
  • 57

Point set intersections are very costly, and you want to absolutely make sure you limit your queries

  • to the least possible function calls
  • on the least possible amount of vertices between both participating geometries

For this you want to

  • first ST_SubDivide your MultiPolygon, resulting in some 300 times less vertices per operation
  • then explicitly JOIN on ST_Intersects to make use of the now more effective index on landcoverpolygons.geom, limiting operations to only the relevant subset
  • while using a CASE decision to avoid any unnecessary call to ST_Intersection
  • and finally get your ST_Centroid on the ST_Collect of those individual intersections that you mention above

Note that

  • it doesn't make sense to transform your geometries at all - especially if landcoverpolygons.geom is actually referenced in EPSG:4326

  • there is no benefit in any of your spatial indexes if more than a few percent of rows would match, and even if the planer chose to use it over the attribute indexes on your relations, it would be highly ineffective, producing a high number of false hits

  • Multi geometries are always bad for spatial relationship analysis, and even more so are geometries with excessive amounts of vertices

  • adding indexes by guess is likely having the opposite effect - get rid of all excessive indexes, run VACUUM ANALYZE on all participating tables and retry; for this particular query only the indexes

    • ON landcoverpolygons USING GIST (geom)
    • ON landcovertype (forest)

    are of interest

Try:

WITH
    mp_sd AS (
        SELECT  ST_Subdivide(<MP>) AS geom
    )
SELECT  id,
        ST_Centroid(its_geom) AS geom
FROM    (
    SELECT  lcp.id,
            ST_Collect(
                CASE ST_Within(lcp.geom, mp_sd.geom)
                    WHEN TRUE THEN lcp.geom
                    ELSE ST_Intersection(lcp.geom, mp_sd.geom)
                END
            ) AS its_geom
    FROM    landcoverpolygons AS lcp
    JOIN    mp_sd
      ON    lcp.geom && mp_sd.geom AND ST_Intersects(lcp.geom, mp_sd.geom)
    WHERE   lcp.name_type <> 'foreign'
      AND   lcp.landcovertype IN (
                SELECT  landcovertype
                FROM    polygons_categories
                WHERE   forest
            )
    GROUP BY
            1
) q
;

Always post the full EXPLAIN ANALYZE output here - some of us know how to make sense of it!