Using PostgreSQL and PostGIS, I have two tables of polygons, and I need to know which of the records in table p1 do not exist in table p2. I do not have additional information available (e.g. ids) - I need to make the determination based solely on the geometry.
A typical database solution is to use a left join
SELECT p1.geom from schema1.parcel p1
JOIN schema2.parcel p2
ON st_equals(p2.geom, p1.geom)
WHERE
p2.pid is null
This works fine for very small numbers of rows, but as the number of rows increases, it becomes very slow. Both geometry fields are indexed using gist. I have ~200K rows in a test set, and I let it run for a few hours and it didn't complete.
I noticed that using on p2.geom = p1.geom
instead of st_equals
performs much faster (a matter of seconds). I might be able to get away with using =
, but the two are not equivalent and I would prefer to use st_equals
.
Is there a generally-accepted best approach for this? Surely, it's a fairly common problem?
I'm wondering if there is a superior approach for writing such a query with st_equals
? Alternatively, it has crossed my mind to do something along the lines of hashing each geometry, storing the hashes, and comparing those instead. Not sure if the expense of doing so is worth it...
Edit: it's probably pertinent to mention that both tables will (likely) have 5-10 million records, and I would expect a relatively small number of differences. Maybe 5-10%, but that's just a guess - I anticipate many matching geometries and few non-matching.
Note: I posted a related question on stackexchange that was more about the Postgres optimizer. To me, they are different enough to warrant a new question...
=
. See gis.stackexchange.com/questions/223342/…~=
checks for bounding box equality.=
is not the same asst_equals
, but one of the comments in that post points out that=
is improved. I may be able to get away with the changed functionality...but I would still prefer st_equals blog.cleverelephant.ca/2017/09/postgis-operators.html