PostGIS 3.5.2 ST_Contains() query on gist is slow
Sebastiaan Couwenberg
sebastic at xs4all.nl
Mon Sep 8 20:23:32 PDT 2025
Since the upgrade to Debian trixie with PostgreSQL 17.6 and PostGIS 3.5.2 the queries to fetch all ways connected to a boundary with nodes within a bounding box are terribly slow.
osm-nl=# SELECT postgis_full_version();
postgis_full_version
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
POSTGIS="3.5.2 dea6d0a" PGSQL="170" GEOS="3.13.1-CAPI-1.19.2" PROJ="9.6.0 NETWORK_ENABLED=OFF URL_ENDPOINT=https://cdn.proj.org USER_WRITABLE_DIRECTORY=/tmp/proj DATABASE_PATH=/usr/share/proj/proj.db" (compiled against PROJ 9.5.1) LIBXML="2.9.14" LIBJSON="0.18" LIBPROTOBUF="1.5.1" WAGYU="0.5.0 (Internal)"
(1 row)
osm-nl=# EXPLAIN (ANALYZE, BUFFERS) SELECT wn.way_id FROM way_nodes AS wn, nodes AS n WHERE wn.node_id = 8646506472 AND wn.node_id = n.id AND ST_Contains(ST_GeomFromEWKT('SRID=4326;POLYGON((6.1198199 52.612195500000006,6.1198199 53.2038323,7.0927397 53.2038323,7.0927397 52.612195500000006,6.1198199 52.612195500000006))'), n.geom);
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Nested Loop (cost=0.99..29.54 rows=1 width=8) (actual time=5648.531..5648.532 rows=0 loops=1)
Buffers: shared hit=6744524 read=845409 written=5
-> Index Scan using idx_way_nodes_node_id on way_nodes wn (cost=0.57..8.59 rows=1 width=16) (actual time=0.021..0.022 rows=1 loops=1)
Index Cond: (node_id = '8646506472'::bigint)
Buffers: shared read=5
-> Index Scan using idx_nodes_geom on nodes n (cost=0.42..20.94 rows=1 width=8) (actual time=5648.507..5648.507 rows=0 loops=1)
Index Cond: (geom @ '0103000020E61000000100000005000000D5A35F11B27A184013A1116C5C4E4A40D5A35F11B27A18402A2F432D179A4A40D529EA27F75E1C402A2F432D179A4A40D529EA27F75E1C4013A1116C5C4E4A40D5A35F11B27A184013A1116C5C4E4A40'::geometry)
Filter: ((id = '8646506472'::bigint) AND st_contains('0103000020E61000000100000005000000D5A35F11B27A184013A1116C5C4E4A40D5A35F11B27A18402A2F432D179A4A40D529EA27F75E1C402A2F432D179A4A40D529EA27F75E1C4013A1116C5C4E4A40D5A35F11B27A184013A1116C5C4E4A40'::geometry, geom))
Rows Removed by Filter: 9886042
Buffers: shared hit=6744524 read=845404 written=5
Planning:
Buffers: shared hit=11 read=15
Planning Time: 0.294 ms
Execution Time: 5648.551 ms
(14 rows)
This is a database with OSM data from Geofabrik created with Osmosis using its pgsnapshot schema.
osm-nl=# \d+ way_nodes; Table "public.way_nodes"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
-------------+---------+-----------+----------+---------+---------+-------------+--------------+-------------
way_id | bigint | | not null | | plain | | |
node_id | bigint | | not null | | plain | | |
sequence_id | integer | | not null | | plain | | |
Indexes:
"pk_way_nodes" PRIMARY KEY, btree (way_id, sequence_id)
"idx_way_nodes_node_id" btree (node_id)
Access method: heap
osm-nl=# \d+ nodes; Table "public.nodes"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
--------------+-----------------------------+-----------+----------+---------+----------+-------------+--------------+-------------
id | bigint | | not null | | plain | | |
version | integer | | not null | | plain | | |
user_id | integer | | not null | | plain | | |
tstamp | timestamp without time zone | | not null | | plain | | |
changeset_id | bigint | | not null | | plain | | |
tags | hstore | | | | extended | | |
geom | geometry(Point,4326) | | | | main | | |
Indexes:
"pk_nodes" PRIMARY KEY, btree (id)
"idx_nodes_geom" gist (geom)
Access method: heap
Increasing the work_mem from 40MB to 400MB did not help as expected as this worked fine on bookworm and earlier.
I suspect there may be a regression in PostGIS 3.5.2, but I'm at a loss on how to confirm and fix that.
The changes in the 3.5.3 NEWS don't seem to be related.
Has anyone encountered this issue as well and/or get suggests solutions?
Kind Regards,
Bas
--
GPG Key ID: 4096R/6750F10AE88D4AF1
Fingerprint: 8182 DE41 7056 408D 6146 50D1 6750 F10A E88D 4AF1
More information about the postgis-users
mailing list