I don't understand why the following query is so slow (with Postgresql 9.6):
SELECT s.pkid AS pkid_site , s.geom AS geom_site , z.pkid AS pkidEmprise, z.geom AS geom_emprise, z.précision_contour FROM traitements.sites_candidats AS s JOIN traitements.zones_sites AS z ON z.pkid_site = s.pkid WHERE s.statut = 'selected' AND z.statut = 'selected'; The structure of the tables is the following:
CREATE TABLE traitements.sites_candidats ( pkid serial PRIMARY KEY, statut varchar(255) NOT NULL, geom geometry(Point, 2154) ); CREATE INDEX ON traitements.sites_candidats (statut); CREATE TABLE traitements.zones_sites ( pkid serial PRIMARY KEY, pkid_site integer NOT NULL, geom geometry(MultiPolygon,2154), statut varchar(100) ); CREATE INDEX zones_sites_idx_pkid_site ON traitements.zones_sites (pkid_site); CREATE INDEX zones_sites_idx_statut ON traitements.zones_sites (statut) ; ALTER TABLE traitements.zones_sites ADD CONSTRAINT zones_sites_references_sites_candidats FOREIGN KEY (pkid_site) REFERENCES traitements.sites_candidats(pkid) ON DELETE CASCADE; (I deleted a couple of columns that are not involved in the query in order to improve readability).
The result of EXPLAIN ANALYZE:
Hash Join (cost=17709.29..152088.29 rows=147368 width=887) (actual time=137.074..879.884 rows=210708 loops=1) Hash Cond: (z.pkid_site = s.pkid) -> Seq Scan on zones_sites z (cost=0.00..85198.14 rows=210717 width=855) (actual time=0.140..384.964 rows=210708 loops=1) Filter: ((statut)::text = 'selected'::text) Rows Removed by Filter: 23 -> Hash (cost=13433.16..13433.16 rows=210490 width=36) (actual time=136.772..136.772 rows=210708 loops=1) Buckets: 65536 Batches: 8 Memory Usage: 2191kB -> Seq Scan on sites_candidats s (cost=0.00..13433.16 rows=210490 width=36) (actual time=3.085..87.774 rows=210708 loops=1) Filter: ((statut)::text = 'selected'::text) Rows Removed by Filter: 90265 Planning time: 0.386 ms Execution time: 888.436 ms It's obviously the JOIN .. ON that consumes time because it does a hash.
Table traitements.sites_candidats has about 300k rows (210k of them with statut='selected') and traitements.zones_sites about 210k rows (nearly 99% of have statut='selected'). The query takes more than 4 minutes.