<div dir="ltr"><div>Hello,</div><div><br></div><div>Thank you for the information.</div><div>I'll try it with PostGIS 3.0.</div><div><br></div><div>Ryo</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">2020年3月5日(木) 19:01 Darafei "Komяpa" Praliaskouski <<a href="mailto:me@komzpa.net">me@komzpa.net</a>>:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hello,<br>
<br>
Equality has been significantly reworked in 3.0. Can you reproduce<br>
your issue in PostGIS 3.0?<br>
<br>
On Thu, Mar 5, 2020 at 9:46 AM Ryo NEYAMA <neyama@toyota-tokyo.tech> wrote:<br>
><br>
> Hello,<br>
><br>
> I had a performance issue when I JOIN two tables by using the equivalence<br>
> of two ST_Point()s.<br>
> I'm wondering if it is a kind of specification...<br>
><br>
> -- SQL statements FROM HERE<br>
> BEGIN;<br>
><br>
> SELECT version(), postgis_version();<br>
><br>
> DROP TABLE IF EXISTS table1;<br>
> DROP TABLE IF EXISTS table2;<br>
><br>
> CREATE TEMPORARY SEQUENCE gen_serial;<br>
><br>
> CREATE TABLE table1 AS (<br>
> SELECT<br>
> nextval('gen_serial') AS id,<br>
> ST_Point(x, y) AS coord<br>
> FROM (<br>
> SELECT<br>
> x, y<br>
> FROM<br>
> (SELECT generate_series(1, 100) x) set_x<br>
> CROSS JOIN<br>
> (SELECT generate_series(1, 100) y) set_y<br>
> ) tmp<br>
> );<br>
><br>
> CREATE TABLE table2 AS (<br>
> SELECT<br>
> nextval('gen_serial') AS id,<br>
> ST_Point(x, y) AS coord<br>
> FROM (<br>
> SELECT<br>
> x, y<br>
> FROM<br>
> (SELECT generate_series(25, 75) x) set_x<br>
> CROSS JOIN<br>
> (SELECT generate_series(25, 75) y) set_y<br>
> ) tmp<br>
> );<br>
><br>
> -- test case (1)<br>
> EXPLAIN ANALYZE<br>
> SELECT<br>
> COUNT(*)<br>
> FROM<br>
> table1<br>
> JOIN<br>
> table2<br>
> ON<br>
> ST_Equals(table1.coord, table2.coord)<br>
> ;<br>
><br>
> -- test case (2)<br>
> EXPLAIN ANALYZE<br>
> SELECT<br>
> COUNT(*)<br>
> FROM<br>
> table1<br>
> JOIN<br>
> table2<br>
> ON<br>
> table1.coord = table2.coord<br>
> ;<br>
><br>
> -- test case (3)<br>
> EXPLAIN ANALYZE<br>
> SELECT<br>
> COUNT(*)<br>
> FROM<br>
> table1<br>
> JOIN<br>
> table2<br>
> ON<br>
> ST_AsText(table1.coord) = ST_AsText(table2.coord)<br>
> ;<br>
><br>
> END;<br>
><br>
> -- SQL statements TO HERE<br>
><br>
> -- Results FROM HERE<br>
> BEGIN<br>
> version<br>
> |<br>
> postgis_version<br>
> ----------------------------------------------------------------------------------------------------------------------------------+---------------------------------------<br>
> PostgreSQL 11.2 (Debian 11.2-1.pgdg90+1) on x86_64-pc-linux-gnu, compiled<br>
> by gcc (Debian 6.3.0-18+deb9u1) 6.3.0 20170516, 64-bit | 2.5 USE_GEOS=1<br>
> USE_PROJ=1 USE_STATS=1<br>
> (1 row)<br>
><br>
> DROP TABLE<br>
> DROP TABLE<br>
> CREATE SEQUENCE<br>
> SELECT 10000<br>
> SELECT 2601<br>
> QUERY PLAN<br>
><br>
> --------------------------------------------------------------------------------------------------------------------------<br>
> Aggregate (cost=7052229.97..7052229.98 rows=1 width=8) (actual<br>
> time=7096.372..7096.373 rows=1 loops=1)<br>
> -> Nested Loop (cost=0.00..7052207.80 rows=8870 width=0) (actual<br>
> time=1692.069..7096.193 rows=2601 loops=1)<br>
> Join Filter: ((table1.coord ~= table2.coord) AND<br>
> _st_equals(table1.coord, table2.coord))<br>
> Rows Removed by Join Filter: 26007399<br>
> -> Seq Scan on table1 (cost=0.00..184.80 rows=10080 width=32)<br>
> (actual time=0.004..0.767 rows=10000 loops=1)<br>
> -> Materialize (cost=0.00..61.60 rows=2640 width=32) (actual<br>
> time=0.000..0.090 rows=2601 loops=10000)<br>
> -> Seq Scan on table2 (cost=0.00..48.40 rows=2640<br>
> width=32) (actual time=0.004..0.244 rows=2601 loops=1)<br>
> Planning Time: 0.136 ms<br>
> Execution Time: 7096.493 ms<br>
> (9 rows)<br>
><br>
> QUERY PLAN<br>
><br>
> --------------------------------------------------------------------------------------------------------------------------<br>
> Aggregate (cost=399474.33..399474.34 rows=1 width=8) (actual<br>
> time=6870.980..6870.980 rows=1 loops=1)<br>
> -> Nested Loop (cost=0.00..399407.80 rows=26611 width=0) (actual<br>
> time=1665.642..6870.790 rows=2601 loops=1)<br>
> Join Filter: (table1.coord = table2.coord)<br>
> Rows Removed by Join Filter: 26007399<br>
> -> Seq Scan on table1 (cost=0.00..184.80 rows=10080 width=32)<br>
> (actual time=0.004..0.870 rows=10000 loops=1)<br>
> -> Materialize (cost=0.00..61.60 rows=2640 width=32) (actual<br>
> time=0.000..0.099 rows=2601 loops=10000)<br>
> -> Seq Scan on table2 (cost=0.00..48.40 rows=2640<br>
> width=32) (actual time=0.004..0.258 rows=2601 loops=1)<br>
> Planning Time: 0.031 ms<br>
> Execution Time: 6871.063 ms<br>
> (9 rows)<br>
><br>
> QUERY PLAN<br>
><br>
> ------------------------------------------------------------------------------------------------------------------------------<br>
> Aggregate (cost=512255.20..512255.21 rows=1 width=8) (actual<br>
> time=44.998..44.998 rows=1 loops=1)<br>
> -> Merge Join (cost=1053.52..511922.56 rows=133056 width=0) (actual<br>
> time=42.285..44.865 rows=2601 loops=1)<br>
> Merge Cond: ((st_astext(table2.coord)) = (st_astext(table1.coord)))<br>
> -> Sort (cost=198.44..205.04 rows=2640 width=32) (actual<br>
> time=4.408..4.514 rows=2601 loops=1)<br>
> Sort Key: (st_astext(table2.coord))<br>
> Sort Method: quicksort Memory: 300kB<br>
> -> Seq Scan on table2 (cost=0.00..48.40 rows=2640<br>
> width=32) (actual time=0.018..3.587 rows=2601 loops=1)<br>
> -> Sort (cost=855.08..880.28 rows=10080 width=32) (actual<br>
> time=37.466..37.760 rows=7329 loops=1)<br>
> Sort Key: (st_astext(table1.coord))<br>
> Sort Method: quicksort Memory: 1166kB<br>
> -> Seq Scan on table1 (cost=0.00..184.80 rows=10080<br>
> width=32) (actual time=0.005..13.276 rows=10000 loops=1)<br>
> Planning Time: 0.088 ms<br>
> Execution Time: 45.104 ms<br>
> (13 rows)<br>
><br>
> COMMIT<br>
> -- Results TO HERE<br>
><br>
> The above three SQL statements, test case (1), (2), and (3) provides<br>
> exactly the same result, i.e. count = 2601.<br>
><br>
> The test case (1) uses ST_Equals and (2) uses '=' for comparison.<br>
> The test case (3) converts a ST_Point to text by using ST_AsText().<br>
> The test case (1)(2) is more intuitive and straightforward than the test<br>
> case (3).<br>
> However, the test case (3) is much faster than the test cases (1) and (2).<br>
><br>
> As described in QUERY PLAN, only the test case (3) could benefit from<br>
> Sort-Merge-Join.<br>
> Is it possible to get the equivalent performance with test case (1) and (2)?<br>
><br>
> Best regards,<br>
> Ryo Neyama<br>
> _______________________________________________<br>
> postgis-users mailing list<br>
> <a href="mailto:postgis-users@lists.osgeo.org" target="_blank">postgis-users@lists.osgeo.org</a><br>
> <a href="https://lists.osgeo.org/mailman/listinfo/postgis-users" rel="noreferrer" target="_blank">https://lists.osgeo.org/mailman/listinfo/postgis-users</a><br>
<br>
<br>
<br>
-- <br>
Darafei Praliaskouski<br>
Support me: <a href="http://patreon.com/komzpa" rel="noreferrer" target="_blank">http://patreon.com/komzpa</a><br>
_______________________________________________<br>
postgis-users mailing list<br>
<a href="mailto:postgis-users@lists.osgeo.org" target="_blank">postgis-users@lists.osgeo.org</a><br>
<a href="https://lists.osgeo.org/mailman/listinfo/postgis-users" rel="noreferrer" target="_blank">https://lists.osgeo.org/mailman/listinfo/postgis-users</a></blockquote></div></div>