PostgreSQL 13.5, PostGIS 3.2, Windows Server 2012.
My table uniteobservation
has 824 605 rows:
CREATE TABLE activite.uniteobservation (
gid serial NOT NULL,
numunobs character varying(20),
typunobs character varying(20),
interpret character varying(60,
datedebut bigint,
datefin integer,
gidoperef integer NOT NULL,
geom geometry(Geometry,2154),
periode character varying(50),
CONSTRAINT "UniteObservation_pkey" PRIMARY KEY (gid),
CONSTRAINT clef_etrangere_prescription FOREIGN KEY (gidoperef)
REFERENCES activite.prescription (gid),
CONSTRAINT epsg_isvalid_check CHECK (
st_x(st_centroid(geom)) >= 99217::double precision AND
st_x(st_centroid(geom)) <= 1242417.2::double precision AND
st_y(st_centroid(geom)) >= 6049646::double precision AND
st_y(st_centroid(geom)) <= 7110480.1::double precision),
CONSTRAINT uniteobservation_geom_notnull CHECK (geom IS NOT NULL),
CONSTRAINT uniteobservation_isvalid_check CHECK (st_isvalid(geom))
I am trying to execute this query:
select o1.gid gid1, o2.gid gid2 from
activite.uniteobservation o1, activite.uniteobservation o2
where st_equals(o1.geom, o2.geom)
and o1.gid < o2.gid
order by o1.gid, o2.gid
There are indexes on gid and geom columns.
CREATE INDEX idx_unobs_gid
ON activite.uniteobservation USING btree (gid);
CREATE INDEX idx_uniteobservation_geom_gist
ON activite.uniteobservation USING gist (geom);
In the execution plan:
"Gather Merge (cost=3220744751.29..3388503442.56 rows=1437831248 width=8)"
" Workers Planned: 2"
" -> Sort (cost=3220743751.27..3222541040.33 rows=718915624 width=8)"
" Sort Key: o1.gid, o2.gid"
" -> Nested Loop (cost=2068.71..3075671069.76 rows=718915624 width=8)"
" -> Parallel Seq Scan on uniteobservation o2 (cost=0.00..97527.85 rows=343585 width=1223)"
" -> Bitmap Heap Scan on uniteobservation o1 (cost=2068.71..8951.15 rows=27 width=1223)"
" Recheck Cond: (gid < o2.gid)"
" Filter: st_equals(geom, o2.geom)"
" -> BitmapAnd (cost=2068.71..2068.71 rows=275 width=0)"
" -> Bitmap Index Scan on idx_uniteobservation_geom_gist (cost=0.00..6.50 rows=825 width=0)"
" Index Cond: (geom ~= o2.geom)"
" -> Bitmap Index Scan on idx_unobs_gid (cost=0.00..2061.95 rows=274868 width=0)"
" Index Cond: (gid < o2.gid)"
If I can see that the nested loop is very x10 expensive due to the Nested Loop.
I am not familiar with query optimization. So is there any way to reduce the cost this query? Currently, it does not even finish.
EDIT With this query :
EXPLAIN (ANALYZE, BUFFERS) select o1.gid gid1, o2.gid gid2 from
activite.uniteobservation o1, activite.uniteobservation o2
where st_equals(o1.geom, o2.geom)
and o1.gid < o2.gid and o2.gid=13
order by o1.gid, o2.gid
Here is the query plan:
"Sort (cost=13180.55..13185.94 rows=2154 width=8) (actual time=0.178..0.183 rows=0 loops=1)"
" Sort Key: o1.gid"
" Sort Method: quicksort Memory: 25kB"
" Buffers: shared read=3"
" -> Nested Loop (cost=5119.17..13061.30 rows=2154 width=8) (actual time=0.161..0.164 rows=0 loops=1)"
" Buffers: shared read=3"
" -> Index Scan using idx_unobs_gid on uniteobservation o2 (cost=0.42..8.44 rows=1 width=1243) (actual time=0.159..0.160 rows=0 loops=1)"
" Index Cond: (gid = 13)"
" Buffers: shared read=3"
" -> Bitmap Heap Scan on uniteobservation o1 (cost=5118.74..13052.58 rows=28 width=1243) (never executed)"
" Recheck Cond: (gid < o2.gid)"
" Filter: st_equals(geom, o2.geom)"
" -> BitmapAnd (cost=5118.74..5118.74 rows=275 width=0) (never executed)"
" -> Bitmap Index Scan on idx_uniteobservation_geom_gist (cost=0.00..34.47 rows=825 width=0) (never executed)"
" Index Cond: (geom ~= o2.geom)"
" -> Bitmap Index Scan on idx_unobs_gid (cost=0.00..5084.01 rows=275144 width=0) (never executed)"
" Index Cond: (gid < o2.gid)"
"Planning Time: 3.798 ms"
"Execution Time: 0.419 ms"
CREATE TABLE
andCREATE INDEX
statements). And always your version of Postgres (and PostGIS). I am thinking of a multicolumn index on(geom, gid)
...activite."UniteObservation_gid_seq"
. That suspiciously looks like you have (or had?) a corresponding table"UniteObservation"
with double-quotes preserving the dreaded mixed-case spelling. But your table's name is stilluniteobservation
, right? No confusion there?AND o2.gid=13
(or some other constant) onto the query? Please show theEXPLAIN (ANALYZE, BUFFERS)
for it.