Thread: Seq scan on zero-parameters function

Seq scan on zero-parameters function

From
"Octavio Alvarez"
Date:
Hi!

   I'd like to know if this is expected behavior. These are two couples of
queries. In each couple, the first one has a WHERE field = function()
condition, just like the second one, but in the form WHERE field =
(SELECT function()). In my opinion, both should have the same execution
plan, as the function has no parameters and, therefore, is constant.

   I'm concerned about this, because the second form looks like a workaround.

*** TESTED IN: PostgreSQL 7.4.1 on i686-pc-cygwin ***

pgdb=# explain analyze select count(*) from t_students where period =
(select current_period_id());
                                                                             QUERY
PLAN

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=127.84..127.84 rows=1 width=0) (actual time=1.000..1.000
rows=1 loops=1)
   InitPlan
     ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual
time=1.000..1.000 rows=1 loops=1)
   ->  Index Scan using i_t_students__period on t_students
(cost=0.00..127.71 rows=44 width=0) (actual time=1.000..1.000 rows=21
loop=1)
         Index Cond: (period = $0)
 Total runtime: 1.000 ms
(6 rows)

pgdb=# explain analyze select count(*) from t_students where period =
(select current_period_id());
                                                                             QUERY
PLAN

-------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=127.84..127.84 rows=1 width=0) (actual time=1.000..1.000
rows=1 loops=1)
   InitPlan
     ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual
time=1.000..1.000 rows=1 loops=1)
   ->  Index Scan using i_t_students__period on t_students
(cost=0.00..127.71 rows=44 width=0) (actual time=1.000..1.000 rows=21
loop=1)
         Index Cond: (period = $0)
 Total runtime: 1.000 ms
(6 rows)

pgdb=# select version();
                                        version
---------------------------------------------------------------------------------------
 PostgreSQL 7.4.1 on i686-pc-cygwin, compiled by GCC gcc (GCC) 3.3.1
(cygming special)
(1 row)

pgdb=#

*** TESTED IN: PostgreSQL 7.3.4 on i386-redhat-linux-gnu ***

pgdb=# explain analyze select count(*) from t_students where period =
current_period_id();
                                                          QUERY PLAN

-------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=182.32..182.32 rows=1 width=0) (actual
time=49077.38..49077.38 rows=1 loops=1)
   ->  Seq Scan on t_students  (cost=0.00..182.22 rows=43 width=0) (actual
time=17993.89..49077.13 rows=21 loops=1)
         Filter: (period = current_period_id())
 Total runtime: 49077.61 msec
(4 rows)

pgdb=# explain analyze select count(*) from t_students where period =
(select current_period_id());
                                                                              QUERY
PLAN

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Aggregate  (cost=125.19..125.19 rows=1 width=0) (actual
time=131.59..131.60 rows=1 loops=1)
   InitPlan
     ->  Result  (cost=0.00..0.01 rows=1 width=0) (actual
time=41.05..41.06 rows=1 loops=1)
   ->  Index Scan using i_t_students__period on t_students
(cost=0.00..125.08 rows=43 width=0) (actual time=131.28..131.48 rows=21
loops=1)
         Index Cond: (period = $0)
 Total runtime: 131.95 msec
(6 rows)

pgdb=# select version();
                             version
-----------------------------------------------------------------
 PostgreSQL 7.3.4 on i386-redhat-linux-gnu, compiled by GCC 2.96
(1 row)




--
Octavio Alvarez.
E-mail: alvarezp@alvarezp.ods.org.

Agradezco que sus correos sean enviados siempre a esta dirección.

Re: Seq scan on zero-parameters function

From
"Octavio Alvarez"
Date:
Tomasz Myrta said:
> Dnia 2004-02-06 08:19, U¿ytkownik Octavio Alvarez napisa³:
>> In each couple, the first one has a WHERE field = function()
>> condition, just like the second one, but in the form WHERE field =
>> (SELECT function()). In my opinion, both should have the same execution
>> plan, as the function has no parameters and, therefore, is constant.
>
> Nope.
>
> What would you say about function without params returning timeofday()?
> Is it constant?

No... :-P ;-)

> If you are sure, that your function returns constant value - declare it
> as IMMUTABLE. (look at CREATE FUNCTION documentation)

Thanks for the hint.

In fact, my current_period_id() is based on time, but it should be
constant along the query execution. I mean, I don't want some records
filtered with some values and other with other values... I'll have an
uncongruent recordset.

Say SELECT [field-list] FROM [complex-join] WHERE sec = datepart('second',
now()); Now suppose the query takes always more than 1 second because of
the complex-join or whatever reason: I will naver have a congruent
recordset.

IMMUTABLE wouldn't help here, only wrapping the function in a subquery. Is
this expected behavior? Is this standards compliant (if it can be
qualified as such)?

Octavio.

--
Octavio Alvarez.
E-mail: alvarezp@alvarezp.ods.org.

Agradezco que sus correos sean enviados siempre a esta dirección.

Re: Seq scan on zero-parameters function

From
Richard Huxton
Date:
On Friday 06 February 2004 07:19, Octavio Alvarez wrote:
> Hi!
>
>    I'd like to know if this is expected behavior. These are two couples of
> queries. In each couple, the first one has a WHERE field = function()
> condition, just like the second one, but in the form WHERE field =
> (SELECT function()). In my opinion, both should have the same execution
> plan, as the function has no parameters and, therefore, is constant.

Not necessarily constant - think about random() or timeofday().
Have you set the attributes on your function?

http://www.postgresql.org/docs/7.4/static/sql-createfunction.html

> pgdb=# explain analyze select count(*) from t_students where period =
> (select current_period_id());

It's not entirely clear to me why this form is different from the other form
though.

--
  Richard Huxton
  Archonet Ltd

Re: Seq scan on zero-parameters function

From
Tom Lane
Date:
Richard Huxton <dev@archonet.com> writes:
> It's not entirely clear to me why this form is different from the other form
> though.

The code that checks for expressions containing unstable functions
doesn't look inside sub-selects.  Arguably this is a bug, but people
were relying on that behavior way back before we had these nice
STABLE/IMMUTABLE tags for functions.  I'm hesitant to change it for
fear of breaking people's apps.

            regards, tom lane