Difference in queryplan for array-contains vs unnest

Started by Paul van der Lindenover 7 years ago1 messagesbugs
Jump to latest
#1Paul van der Linden
paul.vanderlinden@mapcreator.eu

This is the version for unnest:
SELECT *
FROM foo
LEFT JOIN LATERAL (
SELECT 1 AS present
FROM selectionpolies
WHERE st_intersects(selectionpolies.geo, foo.geo) AND
selectionpolies.text in (SELECT unnest(countries.countrycodes) AS unnest FROM countries)
LIMIT 1
) bar ON true
WHERE bar.present IS NULL AND geo && 'BOX(-1.87756 47.05916,-1.60932 47.18086)'::box2d

Nested Loop Left Join (cost=29.87..11662.66 rows=9 width=88)
Output: foo.id, foo.geo, (1)
Filter: ((1) IS NULL)
-> Bitmap Heap Scan on foo (cost=29.73..1982.22 rows=1796 width=84)
Output: foo.id, foo.geo
Recheck Cond: (foo.geo && '01030000000100000005000000B471C45A7C0AFEBF9D9D0C8E92874740B471C45A7C0AFEBFC993A46B269747408FC70C54C6BFF9BFC993A46B269747408FC70C54C6BFF9BF9D9D0C8E92874740B471C45A7C0AFEBF9D9D0C8E92874740'::geometry)
-> Bitmap Index Scan on foo_gidx (cost=0.00..29.29 rows=1796 width=0)
Index Cond: (foo.geo && '01030000000100000005000000B471C45A7C0AFEBF9D9D0C8E92874740B471C45A7C0AFEBFC993A46B269747408FC70C54C6BFF9BFC993A46B269747408FC70C54C6BFF9BF9D9D0C8E92874740B471C45A7C0AFEBF9D9D0C8E92874740'::geometry)
-> Limit (cost=0.14..5.37 rows=1 width=4)
Output: 1
-> Nested Loop Semi Join (cost=0.14..5.37 rows=1 width=4)
Output: 1
Join Filter: (selectionpolies.text = (unnest('{nl}'::text[])))
-> Index Scan using selectionpolies_gidx on public.selectionpolies (cost=0.14..2.60 rows=1 width=8)
Output: selectionpolies.text, selectionpolies.geo
Index Cond: (selectionpolies.geo && foo.geo)
Filter: _st_intersects(selectionpolies.geo, foo.geo)
-> ProjectSet (cost=0.00..0.52 rows=100 width=32)
Output: unnest('{nl}'::text[])
-> Result (cost=0.00..0.01 rows=1 width=0)

For array contains:
SELECT *
FROM foo
LEFT JOIN LATERAL (
SELECT 1 AS present
FROM selectionpolies
WHERE st_intersects(selectionpolies.geo, foo.geo) AND
array[selectionpolies.text]<@( SELECT countries.countrycodes FROM countries)
LIMIT 1
) bar ON true
WHERE bar.present IS NULL AND geo && 'BOX(-1.87756 47.05916,-1.60932 47.18086)'::box2d

Nested Loop Left Join (cost=29.88..6714.68 rows=9 width=88)
Output: foo.id, foo.geo, (1)
Filter: ((1) IS NULL)
-> Bitmap Heap Scan on foo (cost=29.73..1982.22 rows=1796 width=84)
Output: foo.id, foo.geo
Recheck Cond: (foo.geo && '01030000000100000005000000B471C45A7C0AFEBF9D9D0C8E92874740B471C45A7C0AFEBFC993A46B269747408FC70C54C6BFF9BFC993A46B269747408FC70C54C6BFF9BF9D9D0C8E92874740B471C45A7C0AFEBF9D9D0C8E92874740'::geometry)
-> Bitmap Index Scan on foo_gidx (cost=0.00..29.29 rows=1796 width=0)
Index Cond: (foo.geo && '01030000000100000005000000B471C45A7C0AFEBF9D9D0C8E92874740B471C45A7C0AFEBFC993A46B269747408FC70C54C6BFF9BFC993A46B269747408FC70C54C6BFF9BF9D9D0C8E92874740B471C45A7C0AFEBF9D9D0C8E92874740'::geometry)
-> Limit (cost=0.15..2.62 rows=1 width=4)
Output: 1
InitPlan 1 (returns $0)
-> Result (cost=0.00..0.01 rows=1 width=32)
Output: '{nl}'::text[]
-> Index Scan using selectionpolies_gidx on public.selectionpolies (cost=0.14..2.61 rows=1 width=4)
Output: 1
Index Cond: (selectionpolies.geo && foo.geo)
Filter: ((ARRAY[selectionpolies.text] <@ $0) AND _st_intersects(selectionpolies.geo, foo.geo))

So in the array-contains case, the selectionpolies are filtered on the text column, while in the unnest case that filtering is postponed to the nested loop semi join (and thus calculating the st_intersects on too much (large!) polygons) despite the planner knowing it's only one record.

Obviously the workaround will be to use the array-contains version, but I thought I mention it anyway because this could be a serious performance dip

Paul van der Linden | MapCreator
Bogert 31-06, 5612 LX, Eindhoven, The Netherlands
Main Office: +31 40 264 5120
MapCreator.eu<http://www.mapcreator.eu/&gt; | [cid:image001.png@01D2FCB9.37565600] <https://www.instagram.com/maps4news/&gt; [cid:image002.png@01D2FCB9.37565600] <https://twitter.com/maps4news&gt; [cid:image003.png@01D2FCB9.37565600] <https://www.linkedin.com/company/maps4news&gt;

[cid:image004.png@01D2FCB9.37565600]<http://www.mapcreator.eu/&gt;

[cid:image005.png@01D2FCB9.37565600] <http://www.maps4news.com/&gt; [cid:image006.png@01D2FCB9.37565600] <http://www.maps4mail.com/&gt;

Attachments:

image001.pngimage/png; name=image001.pngDownload
image002.pngimage/png; name=image002.pngDownload
image003.pngimage/png; name=image003.pngDownload
image004.pngimage/png; name=image004.pngDownload
image005.pngimage/png; name=image005.pngDownload
image006.pngimage/png; name=image006.pngDownload