Re: Surprising SeqScan of appendRel that can't contribute any rows to the result

From: Dmytro Astapov <dastapov(at)gmail(dot)com>
To: David Rowley <dgrowleyml(at)gmail(dot)com>
Cc: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: Re: Surprising SeqScan of appendRel that can't contribute any rows to the result
Date: 2024-12-18 00:36:32
Message-ID: CAFQUnFgU2UPArb7cSA=Wimhm4W3f34U5xXTPQPyY1DC9YbTNgw@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Thank you for the very detailed answer, much appreciated!

For the benefit of people who might find this in the future via search: so
far the best workaround seems to be something along the lines of:

alter table partB add column always_null bigint;
create index on partB(always_null);

And then I change vw so that instead of constant NULL I expose this column
instead. Thenat instead of seqscan I get index scan on always_null which
(relatively) quickly yields zero rows.

On Wed, 18 Dec 2024, 00:08 David Rowley, <dgrowleyml(at)gmail(dot)com> wrote:

> On Wed, 18 Dec 2024 at 12:17, Dmytro Astapov <dastapov(at)gmail(dot)com> wrote:
> > Surprisingly, this does SeqScan on partB in NestedLoops over some_ids
> with a filter `some_ids.id = NULL::bigint`:
> >
> > Nested Loop (cost=0.29..359.16 rows=200 width=24)
> >   -> Seq Scan on some_ids i (cost=0.00..1.02 rows=2 width=8)
> >   -> Append (cost=0.29..178.56 rows=51 width=16)
> >         -> Index Scan using parta_payload_idx on parta (cost=0.29..8.30
> rows=1 width=16)
> >               Index Cond: (payload = i.id)
> >         -> Seq Scan on partb (cost=0.00..170.00 rows=50 width=16)
> >               Filter: (i.id = NULL::bigint)
> >
> > At the same time `explain select * from vw where payload = 1` correctly
> skips over partB entirely (the node is eliminated from execution plan), and
> so does:
> > explain select * from vw where payload in (1,2);
> >
> > However, any query that does not use explicit literal values still leads
> to SeqScan access on partB, such as:
> > explain select * from vw where payload in (select id from some_ids);
> > explain select * from vw where payload = ANY(ARRAY(select id from
> some_ids));
> > or various forms of joins
> >
> > Do you know if this is expected/documented, or is this a bug?
>
> TL;DR is it's not a bug and expected behaviour.
>
> We tend not to do much in terms of documentation about which
> optimisations the query planner does, so it's probably not documented
> anywhere aside from perhaps the source code. It might be possible for
> us to eliminate the scan to "partb" for the first of the plans shown
> above. However, the code that applies in your example case where the
> planner does manage to eliminate the scan does so using "base" quals,
> i.e. quals that are pushed down into the scan level. See
> apply_child_basequals(). For the Nested Loop example, the i.id =
> NULL::bigint isn't a base qual, so it does not work for that case.
> When we're building paramerised paths, as per what's used in your
> Nested Loop example above, we've already done the work to eliminate
> non-matching union children. We don't really have any concept of "this
> union child does not match for this specific parameterisation", so
> we'd need to invent something to do that (which perhaps is just
> removing or not adding the particular unneeded subpath from the Append
> pathlist.)
>
> For the other cases that depend on the results from subqueries, it's
> more tricky and in many cases not possible to eliminate the scans
> during query planner for those cases as the planner does not have
> information to know what will be returned by the subqueries. There
> might be something very limited we can do in terms of looking to see
> if the operator is strict or not so that we at least know that NULLs
> will never match, but that might be quite a corner case that it might
> not be worth the complexity to make that work. Someone might need to
> write it and see how complex it is to implement before we'd know if it
> was a worthwhile optimisation or not.
>
> David
>

In response to

Browse pgsql-bugs by date

  From Date Subject
Next Message Tom Lane 2024-12-18 01:40:21 Re: Surprising SeqScan of appendRel that can't contribute any rows to the result
Previous Message David Rowley 2024-12-18 00:08:10 Re: Surprising SeqScan of appendRel that can't contribute any rows to the result