From Julien.MONTICOLO at strasbourg.eu Mon Jun 1 07:47:51 2026 From: Julien.MONTICOLO at strasbourg.eu (MONTICOLO Julien) Date: Mon, 1 Jun 2026 14:47:51 +0000 Subject: Performance of ST_OrderingEquals Message-ID: <9ea6f81cb2c148dab4de47041f98e61b@strasbourg.eu> Hello everyone, I recently worked on a query to check duplicates. I initially used ST_OrderingEquals to find exact matches. But with a great number of geometries, the query takes a long time. I changed the ST_OrderingEquals by comparison of WKB and this is a lot faster. Here the code to reproduce. I generate a table with 20000 points in the RGF93 / Lambert-93, french main CRS. SELECT version() ; -- PostgreSQL 16.9 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-26), 64-bit SELECT postgis_version(); -- 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1 SELECT ROW_NUMBER() OVER()::BIGINT AS id, ST_POINT( CEIL(100000 + RANDOM() * 1100000), CEIL(6000000 + RANDOM() * 1100000), 2154 )::GEOMETRY(POINT, 2154) AS geom INTO TEMPORARY TABLE my_point_table FROM GENERATE_SERIES(1, 20000) ; WITH pt_tab_with_dup AS ( SELECT id, geom FROM my_point_table UNION ALL SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) ) SELECT d1.id FROM pt_tab_with_dup d1, pt_tab_with_dup d2 WHERE d1.id > d2.id AND ST_OrderingEquals(d1.geom, d2.geom) ; -- 2 min 36 sec WITH pt_tab_with_dup AS ( SELECT id, geom FROM my_point_table UNION ALL SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) ) SELECT d1.id FROM pt_tab_with_dup d1, pt_tab_with_dup d2 WHERE d1.id > d2.id AND ST_AsBinary(d1.geom) = ST_AsBinary(d2.geom) ; -- 0.153 sec I think it's correct. Are there any cases where it doesn't work ? If so, why not improve the ST_OrderingEquals by comparing the WKB ? Kind regards, Julien Monticolo -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- Ce message est ?tabli ? usage exclusif de son destinataire. Toute utilisation ou diffusion, partielle ou totale, doit ?tre pr?alablement autoris?e. Tout message ?lectronique est susceptible d'alt?ration et son int?grit? ne peut ?tre assur?e. L'exp?diteur d?cline toute responsabilit? au titre de ce message s'il a ?t? modifi? ou falsifi?. Si vous n'?tes pas destinataire de ce message, merci de le d?truire et d'avertir l'exp?diteur. Ville et Eurom?tropole de Strasbourg -------------- next part -------------- An HTML attachment was scrubbed... URL: From florian.nadler at cybertec.at Mon Jun 1 23:36:26 2026 From: florian.nadler at cybertec.at (Florian Nadler) Date: Tue, 2 Jun 2026 08:36:26 +0200 Subject: Coordinate transformations with pipelines In-Reply-To: References: Message-ID: <36f42de3-5fb8-4370-bbaa-0ccbb242d061@cybertec.at> Dear Antonio, sorry for being late, I took a deeper look at the operatios output. I believe the reason why Proj did not choose Operation 1/2 as winner is the related extent (stored in the extent table in proj.db), which does not cover your coordinate. To cross-check I adopted the extent in proj.db and executed your command again from the command line: cs2cs EPSG:23033 EPSG:25833 ? ? ? ? ? ? ? ? ? ? ? ? ? ? 541000 4516000 540931.34? ? ? ?4515810.60 0.00 Cheers, Florian Am 26.02.2026 um 11:28 schrieb Antonio Valanzano: > cs2cs EPSG:23033 EPSG:25833 > 541000 4516000 -- CYBERTEC PostgreSQL International GmbH R?merstra?e 19, A-2752 W?llersdorf Web: https://www.cybertec-postgresql.com From pramsey at cleverelephant.ca Thu Jun 4 08:18:47 2026 From: pramsey at cleverelephant.ca (Paul Ramsey) Date: Thu, 4 Jun 2026 08:18:47 -0700 Subject: Fwd: Performance of ST_OrderingEquals In-Reply-To: References: <9ea6f81cb2c148dab4de47041f98e61b@strasbourg.eu> Message-ID: The problem seems to be higher up. The actual implementation of ST_OrderingEquals calls into gserialized_cmp quite quickly and that function is deliberately very very vast. I can actually make your query even faster by just using "where d1.geom = d2.geom" which directly calls into gserialized_cmp. The issue is not the function, but the plan. Using the = operator we get a HashJoin, using the WKB we get a MergeJoin, while using the ST_OrderingEquals function we get a NestedLoopJoin, even if we push the cost of the joining function down to nothing. ALTER FUNCTION ST_OrderingEquals (geometry, geometry) COST 0.00001; I'm not sure if there's any way around this, the NestedLoopJoin might be a consequence of the join condition being a function rather than an operator, it would take some digging to figure why PostgreSQL is choosing it. On Mon, Jun 1, 2026 at 7:55?AM MONTICOLO Julien wrote: > > Hello everyone, > > > > I recently worked on a query to check duplicates. > > I initially used ST_OrderingEquals to find exact matches. > > But with a great number of geometries, the query takes a long time. > > I changed the ST_OrderingEquals by comparison of WKB and this is a lot faster. > > > > Here the code to reproduce. I generate a table with 20000 points in the RGF93 / Lambert-93, french main CRS. > > > > SELECT version() ; -- PostgreSQL 16.9 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-26), 64-bit > > SELECT postgis_version(); -- 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1 > > > > SELECT > > ROW_NUMBER() OVER()::BIGINT AS id, > > ST_POINT( > > CEIL(100000 + RANDOM() * 1100000), > > CEIL(6000000 + RANDOM() * 1100000), > > 2154 > > )::GEOMETRY(POINT, 2154) AS geom > > INTO TEMPORARY TABLE my_point_table > > FROM > > GENERATE_SERIES(1, 20000) > > ; > > > > WITH pt_tab_with_dup AS ( > > SELECT id, geom FROM my_point_table UNION ALL > > SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) > > ) > > SELECT > > d1.id > > FROM > > pt_tab_with_dup d1, > > pt_tab_with_dup d2 > > WHERE > > d1.id > d2.id > > AND ST_OrderingEquals(d1.geom, d2.geom) > > ; -- 2 min 36 sec > > > > > > WITH pt_tab_with_dup AS ( > > SELECT id, geom FROM my_point_table UNION ALL > > SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) > > ) > > SELECT > > d1.id > > FROM > > pt_tab_with_dup d1, > > pt_tab_with_dup d2 > > WHERE > > d1.id > d2.id > > AND ST_AsBinary(d1.geom) = ST_AsBinary(d2.geom) > > ; -- 0.153 sec > > > > > > I think it?s correct. > > Are there any cases where it doesn?t work ? If so, why not improve the ST_OrderingEquals by comparing the WKB ? > > > > Kind regards, > > Julien Monticolo > > > > > > Ce message est ?tabli ? usage exclusif de son destinataire. > Toute utilisation ou diffusion, partielle ou totale, doit ?tre pr?alablement autoris?e. > > Tout message ?lectronique est susceptible d'alt?ration et son int?grit? ne peut ?tre assur?e. > L'exp?diteur d?cline toute responsabilit? au titre de ce message s'il a ?t? modifi? ou falsifi?. > > Si vous n'?tes pas destinataire de ce message, merci de le d?truire et d'avertir l'exp?diteur. > > Ville et Eurom?tropole de Strasbourg From me at komzpa.net Sun Jun 7 19:17:46 2026 From: me at komzpa.net (=?UTF-8?Q?Darafei_=22Kom=D1=8Fpa=22_Praliaskouski?=) Date: Mon, 8 Jun 2026 06:17:46 +0400 Subject: h3-pg 4.5.0 released Message-ID: h3-pg 4.5.0 is released. This is the first h3-pg release under the PostGIS umbrella. h3-pg provides PostgreSQL bindings for the H3 hierarchical hexagonal geospatial indexing library, with optional PostGIS integration through the h3_postgis extension. Details here: https://github.com/postgis/h3-pg/releases/tag/v4.5.0 The release is also available on PGXN: https://pgxn.org/dist/h3/ Highlights include bundled H3 core 4.5.0, new bindings for newer upstream H3 APIs, GiST operator class work for h3index, PostgreSQL 17+ maintenance-operation fixes, SP-GiST fixes, and improved h3_postgis geometry/polygonization behavior. Please report issues by replying to this email or reporting them on GitHub: https://github.com/postgis/h3-pg/issues Thanks, Darafei PostGIS Development Team -------------- next part -------------- An HTML attachment was scrubbed... URL: From me at komzpa.net Wed Jun 10 19:41:14 2026 From: me at komzpa.net (=?UTF-8?Q?Darafei_=22Kom=D1=8Fpa=22_Praliaskouski?=) Date: Thu, 11 Jun 2026 06:41:14 +0400 Subject: Performance of ST_OrderingEquals In-Reply-To: References: <9ea6f81cb2c148dab4de47041f98e61b@strasbourg.eu> Message-ID: Can we fix it using the same mechanics as ST_Intersects injecting the operators into the plan? Like https://github.com/postgis/postgis/pull/875 On Thu, Jun 4, 2026 at 7:19?PM Paul Ramsey via postgis-users < postgis-users at lists.osgeo.org> wrote: > The problem seems to be higher up. The actual implementation of > ST_OrderingEquals calls into gserialized_cmp quite quickly and that > function is deliberately very very vast. I can actually make your > query even faster by just using "where d1.geom = d2.geom" which > directly calls into gserialized_cmp. The issue is not the function, > but the plan. Using the = operator we get a HashJoin, using the WKB we > get a MergeJoin, while using the ST_OrderingEquals function we get a > NestedLoopJoin, even if we push the cost of the joining function down > to nothing. > > ALTER FUNCTION ST_OrderingEquals (geometry, geometry) COST 0.00001; > > I'm not sure if there's any way around this, the NestedLoopJoin might > be a consequence of the join condition being a function rather than an > operator, it would take some digging to figure why PostgreSQL is > choosing it. > > On Mon, Jun 1, 2026 at 7:55?AM MONTICOLO Julien > wrote: > > > > Hello everyone, > > > > > > > > I recently worked on a query to check duplicates. > > > > I initially used ST_OrderingEquals to find exact matches. > > > > But with a great number of geometries, the query takes a long time. > > > > I changed the ST_OrderingEquals by comparison of WKB and this is a lot > faster. > > > > > > > > Here the code to reproduce. I generate a table with 20000 points in the > RGF93 / Lambert-93, french main CRS. > > > > > > > > SELECT version() ; -- PostgreSQL 16.9 on x86_64-pc-linux-gnu, compiled > by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-26), 64-bit > > > > SELECT postgis_version(); -- 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1 > > > > > > > > SELECT > > > > ROW_NUMBER() OVER()::BIGINT AS id, > > > > ST_POINT( > > > > CEIL(100000 + RANDOM() * 1100000), > > > > CEIL(6000000 + RANDOM() * 1100000), > > > > 2154 > > > > )::GEOMETRY(POINT, 2154) AS geom > > > > INTO TEMPORARY TABLE my_point_table > > > > FROM > > > > GENERATE_SERIES(1, 20000) > > > > ; > > > > > > > > WITH pt_tab_with_dup AS ( > > > > SELECT id, geom FROM my_point_table UNION ALL > > > > SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) > > > > ) > > > > SELECT > > > > d1.id > > > > FROM > > > > pt_tab_with_dup d1, > > > > pt_tab_with_dup d2 > > > > WHERE > > > > d1.id > d2.id > > > > AND ST_OrderingEquals(d1.geom, d2.geom) > > > > ; -- 2 min 36 sec > > > > > > > > > > > > WITH pt_tab_with_dup AS ( > > > > SELECT id, geom FROM my_point_table UNION ALL > > > > SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) > > > > ) > > > > SELECT > > > > d1.id > > > > FROM > > > > pt_tab_with_dup d1, > > > > pt_tab_with_dup d2 > > > > WHERE > > > > d1.id > d2.id > > > > AND ST_AsBinary(d1.geom) = ST_AsBinary(d2.geom) > > > > ; -- 0.153 sec > > > > > > > > > > > > I think it?s correct. > > > > Are there any cases where it doesn?t work ? If so, why not improve the > ST_OrderingEquals by comparing the WKB ? > > > > > > > > Kind regards, > > > > Julien Monticolo > > > > > > > > > > > > Ce message est ?tabli ? usage exclusif de son destinataire. > > Toute utilisation ou diffusion, partielle ou totale, doit ?tre > pr?alablement autoris?e. > > > > Tout message ?lectronique est susceptible d'alt?ration et son int?grit? > ne peut ?tre assur?e. > > L'exp?diteur d?cline toute responsabilit? au titre de ce message s'il a > ?t? modifi? ou falsifi?. > > > > Si vous n'?tes pas destinataire de ce message, merci de le d?truire et > d'avertir l'exp?diteur. > > > > Ville et Eurom?tropole de Strasbourg > -------------- next part -------------- An HTML attachment was scrubbed... URL: From pramsey at cleverelephant.ca Thu Jun 11 11:07:55 2026 From: pramsey at cleverelephant.ca (Paul Ramsey) Date: Thu, 11 Jun 2026 11:07:55 -0700 Subject: Performance of ST_OrderingEquals In-Reply-To: References: <9ea6f81cb2c148dab4de47041f98e61b@strasbourg.eu> Message-ID: That seems like it would work, but then I wonder if changing ST_OrderingEquals(A, B) to a SQL language function that just does A = B would work just as well? PostgreSQL generally inlines SQL functions. P. On Wed, Jun 10, 2026 at 7:41?PM Darafei "Kom?pa" Praliaskouski wrote: > > Can we fix it using the same mechanics as ST_Intersects injecting the operators into the plan? Like https://github.com/postgis/postgis/pull/875 > > On Thu, Jun 4, 2026 at 7:19?PM Paul Ramsey via postgis-users wrote: >> >> The problem seems to be higher up. The actual implementation of >> ST_OrderingEquals calls into gserialized_cmp quite quickly and that >> function is deliberately very very vast. I can actually make your >> query even faster by just using "where d1.geom = d2.geom" which >> directly calls into gserialized_cmp. The issue is not the function, >> but the plan. Using the = operator we get a HashJoin, using the WKB we >> get a MergeJoin, while using the ST_OrderingEquals function we get a >> NestedLoopJoin, even if we push the cost of the joining function down >> to nothing. >> >> ALTER FUNCTION ST_OrderingEquals (geometry, geometry) COST 0.00001; >> >> I'm not sure if there's any way around this, the NestedLoopJoin might >> be a consequence of the join condition being a function rather than an >> operator, it would take some digging to figure why PostgreSQL is >> choosing it. >> >> On Mon, Jun 1, 2026 at 7:55?AM MONTICOLO Julien >> wrote: >> > >> > Hello everyone, >> > >> > >> > >> > I recently worked on a query to check duplicates. >> > >> > I initially used ST_OrderingEquals to find exact matches. >> > >> > But with a great number of geometries, the query takes a long time. >> > >> > I changed the ST_OrderingEquals by comparison of WKB and this is a lot faster. >> > >> > >> > >> > Here the code to reproduce. I generate a table with 20000 points in the RGF93 / Lambert-93, french main CRS. >> > >> > >> > >> > SELECT version() ; -- PostgreSQL 16.9 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 8.5.0 20210514 (Red Hat 8.5.0-26), 64-bit >> > >> > SELECT postgis_version(); -- 3.4 USE_GEOS=1 USE_PROJ=1 USE_STATS=1 >> > >> > >> > >> > SELECT >> > >> > ROW_NUMBER() OVER()::BIGINT AS id, >> > >> > ST_POINT( >> > >> > CEIL(100000 + RANDOM() * 1100000), >> > >> > CEIL(6000000 + RANDOM() * 1100000), >> > >> > 2154 >> > >> > )::GEOMETRY(POINT, 2154) AS geom >> > >> > INTO TEMPORARY TABLE my_point_table >> > >> > FROM >> > >> > GENERATE_SERIES(1, 20000) >> > >> > ; >> > >> > >> > >> > WITH pt_tab_with_dup AS ( >> > >> > SELECT id, geom FROM my_point_table UNION ALL >> > >> > SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) >> > >> > ) >> > >> > SELECT >> > >> > d1.id >> > >> > FROM >> > >> > pt_tab_with_dup d1, >> > >> > pt_tab_with_dup d2 >> > >> > WHERE >> > >> > d1.id > d2.id >> > >> > AND ST_OrderingEquals(d1.geom, d2.geom) >> > >> > ; -- 2 min 36 sec >> > >> > >> > >> > >> > >> > WITH pt_tab_with_dup AS ( >> > >> > SELECT id, geom FROM my_point_table UNION ALL >> > >> > SELECT id * -1, geom FROM my_point_table TABLESAMPLE BERNOULLI (10) >> > >> > ) >> > >> > SELECT >> > >> > d1.id >> > >> > FROM >> > >> > pt_tab_with_dup d1, >> > >> > pt_tab_with_dup d2 >> > >> > WHERE >> > >> > d1.id > d2.id >> > >> > AND ST_AsBinary(d1.geom) = ST_AsBinary(d2.geom) >> > >> > ; -- 0.153 sec >> > >> > >> > >> > >> > >> > I think it?s correct. >> > >> > Are there any cases where it doesn?t work ? If so, why not improve the ST_OrderingEquals by comparing the WKB ? >> > >> > >> > >> > Kind regards, >> > >> > Julien Monticolo >> > >> > >> > >> > >> > >> > Ce message est ?tabli ? usage exclusif de son destinataire. >> > Toute utilisation ou diffusion, partielle ou totale, doit ?tre pr?alablement autoris?e. >> > >> > Tout message ?lectronique est susceptible d'alt?ration et son int?grit? ne peut ?tre assur?e. >> > L'exp?diteur d?cline toute responsabilit? au titre de ce message s'il a ?t? modifi? ou falsifi?. >> > >> > Si vous n'?tes pas destinataire de ce message, merci de le d?truire et d'avertir l'exp?diteur. >> > >> > Ville et Eurom?tropole de Strasbourg