- PostGIS version: 3.1
- PostgreSQL version: 12.3
- The machine I am working with has: 126G RAM, 48 CPU cores
Info:
I am getting started with PostGIS.
My goal is to get all the matching data between two points.
lv.geopoint and sub.geopoint both are GEOGRAPHY Points (SRID: 4326) and have GIST indexes on them.
My sub SELECT returns about 3k lines, my ‘valeurs_foncieres’ table however has 14 000 000 lines.
I do have BTREE indexes on valeurs_foncieres.id, caracteristiques_2018.id, caracteristiques_2018.num_acc, usagers_2018.id, usagers_2018.num_acc, vehicules_2018.id, vehicules_2018.num_acc.
The problem:
The query gets exponentially slow as I increase the distance of ST_DWithin.
- Precision 100: 2sec
- Precision 1 000: 10sec
- Precision 10 000: 6min
Here is the query:
SELECT
DISTINCT(sub.num_acc),
sub.geopoint,
sub.id
FROM
(
SELECT
DISTINCT(u.num_acc) AS unumacc, c.*
FROM
usagers_2018 u
INNER JOIN vehicules_2018 v ON
u.num_acc = v.num_acc
INNER JOIN caracteristiques_2018 c ON
u.num_acc = c.num_acc
WHERE
u.grav = '2'
ORDER BY
c.id
) AS sub
INNER JOIN valeurs_foncieres vf ON
ST_DWithin(vf.geopoint,
sub.geog,
1000,
FALSE);
Here is the EXPLAIN:
HashAggregate (cost=265577998.10..265578004.81 rows=671 width=49)
Group Key: c.num_acc, c.geopoint, c.id
-> Nested Loop (cost=9948.38..264845621.97 rows=97650150 width=49)
-> Unique (cost=9947.84..10316.67 rows=6706 width=170)
-> Sort (cost=9947.84..9964.60 rows=6706 width=170)
Sort Key: c.id, u.num_acc, c.an, c.mois, c.jour, c.hrmn, c.lum, c.agg, c."int", c.atm, c.col, c.com, c.adr, c.gps, c.lat, c.long, c.dep, c.lat_gps, c.long_gps, c.geopoint, c.geog
-> Gather (cost=3200.48..9521.63 rows=6706 width=170)
Workers Planned: 1
-> Nested Loop (cost=2200.48..7851.03 rows=3945 width=170)
Join Filter: ((u.num_acc)::text = (v.num_acc)::text)
-> Parallel Hash Join (cost=2200.06..6686.70 rows=2075 width=170)
Hash Cond: ((c.num_acc)::text = (u.num_acc)::text)
-> Parallel Seq Scan on caracteristiques_2018 c (cost=0.00..2859.90 rows=33990 width=157)
-> Parallel Hash (cost=2174.12..2174.12 rows=2075 width=13)
-> Parallel Seq Scan on usagers_2018 u (cost=0.00..2174.12 rows=2075 width=13)
Filter: ((grav)::text = '2'::text)
-> Index Only Scan using vehicules_2018_num_acc_idx on vehicules_2018 v (cost=0.42..0.54 rows=2 width=13)
Index Cond: (num_acc = (c.num_acc)::text)
-> Index Scan using valeurs_foncieres_geopoint_idx on valeurs_foncieres vf (cost=0.54..39477.72 rows=1456 width=32)
Index Cond: (geopoint && _st_expand(c.geog, '1000'::double precision))
Filter: st_dwithin(geopoint, c.geog, '1000'::double precision, false)
JIT:
Functions: 30
Options: Inlining true, Optimization true, Expressions true, Deforming true
Questions:
Is this normal? How can I decrease the execution time?