Re: constant scalar subselect no longer equivalent to constant?

From: merlyn(at)stonehenge(dot)com (Randal L(dot) Schwartz)
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: pgsql-general(at)postgresql(dot)org
Subject: Re: constant scalar subselect no longer equivalent to constant?
Date: 2003-03-14 15:57:52
Message-ID: 86k7f2rldr.fsf@red.stonehenge.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

>>>>> "Tom" == Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> writes:

Tom> FWIW, you don't need a subselect here anymore; it should work as well
Tom> (or as poorly) to do "where stamp > (now() - '1 hour' :: interval)".

Ahh. In 7.2, that was seen as a "calculate a lot" expression, so
I ended up with a seq scan. The subselect kludge was enough for it
to compute it once, and figure out that it could use the index.

>> In 7.3.2, I get a sequential scan! Ugh! It takes about 15 seconds.

Tom> Can you force an indexscan by doing "set enable_seqscan to off"?

Yes. That does it, but of course, I'd rather not change global status
thingies that way. :)

Tom> If not, the problem is likely a datatype mismatch as Josh suggested.

Tom> If you can, then the problem is that the planner doesn't think this is
Tom> selective enough to justify an indexscan. (I'm kinda surprised that
Tom> 7.2 wouldn't have thought the same.) The difficulty is that since
Tom> now() isn't a constant, the planner doesn't know what value the stamp
Tom> column will get compared to, and so it has to fall back on a default
Tom> selectivity estimate that will not be favorable to an indexscan.

So this changed between 7.2 and 7.3?

What's odd is that even writing a function didn't help:

add function ago(interval) returns timestamp with time zone
stable
language 'sql'
as 'select now() - $1';

I thought the addition of the "stable" keyword would make the return
value be the same as a constant. It's not enough, apparently. Is
that a bug, that a stable function and a constant are planned
differently?

Tom> If that's your problem, the answer is to add a dummy condition to turn
Tom> the query into a range scan. This should work:
Tom> where stamp > (now() - '1 hour'::interval)
Tom> and stamp < (now() + '1 hour'::interval);
Tom> The planner still doesn't know the selectivity of the now() conditions,
Tom> but its default estimate for a range query is lots tighter than for
Tom> a one-sided inequality. It should be willing to indexscan this way.

Ahh! It does!

explain select stamp from requests where stamp between now() - '1 hour'::interval and now();

does in fact give me an index scan by default.

Thanks for the workaround. This planner stuff always seems like black
magic. :)

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<merlyn(at)stonehenge(dot)com> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Randal L. Schwartz 2003-03-14 16:01:39 Re: constant scalar subselect no longer equivalent to constant?
Previous Message Tom Lane 2003-03-14 15:44:30 Re: Redefining LIKE operator