Thread: Question about simple function folding optimization

Question about simple function folding optimization

From
Stephan Szabo
Date:
I noticed today (while trying to answer a question) that the following
doesn't seem to use the index on reasonably recent sources whereas it
seems to have at 7.3.1.

create table b1(a int, b text);
create function fold_clients(int, text) returns text as 'select
$1 || ''_'' || upper($2)' language 'sql' immutable;
create index b1ind on b1(fold_clients(a,b));
set enable_seqscan=off;
explain select * from b1 where (fold_clients(a,b))='1_A';

Should that work to use the index or was it just a fluke that it worked in
the past? I think that it's an issue that the function is being expanded
inline (the explain looks like:)
                           QUERY PLAN
-------------------------------------------------------------------Seq Scan on b1  (cost=100000000.00..100000032.50
rows=6width=36)  Filter: ((((a)::text || '_'::text) || upper(b)) = '1_A'::text)
 

which makes it not realize it can use the index.

It's easy to get around for simple functions like this since you can just
make a plpgsql function that returns the expression, but we should at
least note it in the release notes since it's likely to catch people by
surprise.



Re: Question about simple function folding optimization

From
Tom Lane
Date:
Stephan Szabo <sszabo@megazone23.bigpanda.com> writes:
> I noticed today (while trying to answer a question) that the following
> doesn't seem to use the index on reasonably recent sources whereas it
> seems to have at 7.3.1.

> create table b1(a int, b text);
> create function fold_clients(int, text) returns text as 'select
> $1 || ''_'' || upper($2)' language 'sql' immutable;
> create index b1ind on b1(fold_clients(a,b));
> set enable_seqscan=off;
> explain select * from b1 where (fold_clients(a,b))='1_A';

Hmm.  That's an unexpected downside of the recent change to inline
simple SQL functions :-(.  The inlined expression no longer looks
like a match to the index.

The simplest answer is probably to convert the function to plpgsql,
which would probably give better performance for index access anyway.
But I wonder whether any better answer is possible.  I don't want to
give up on the inlining optimization --- anyone see another fix?
        regards, tom lane



Re: Question about simple function folding optimization

From
Joe Conway
Date:
Tom Lane wrote:
> Hmm.  That's an unexpected downside of the recent change to inline
> simple SQL functions :-(.  The inlined expression no longer looks
> like a match to the index.
> 
> The simplest answer is probably to convert the function to plpgsql,
> which would probably give better performance for index access anyway.
> But I wonder whether any better answer is possible.  I don't want to
> give up on the inlining optimization --- anyone see another fix?
> 

Would changing the function from immutable to stable work (similar to 
the other day)?

Joe



Re: Question about simple function folding optimization

From
Tom Lane
Date:
Joe Conway <mail@joeconway.com> writes:
> Would changing the function from immutable to stable work (similar to 
> the other day)?

No; it won't prevent inlining, but it *will* prevent you from using it
as an index function ...
        regards, tom lane



Re: Question about simple function folding optimization

From
Bruno Wolff III
Date:
On Wed, Apr 09, 2003 at 11:54:23 -0400, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> 
> The simplest answer is probably to convert the function to plpgsql,
> which would probably give better performance for index access anyway.
> But I wonder whether any better answer is possible.  I don't want to
> give up on the inlining optimization --- anyone see another fix?

Include an option for function definitions to not allow the function
being defined to be inlined.



Re: Question about simple function folding optimization

From
Tom Lane
Date:
Bruno Wolff III <bruno@wolff.to> writes:
>   Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> But I wonder whether any better answer is possible.  I don't want to
>> give up on the inlining optimization --- anyone see another fix?

> Include an option for function definitions to not allow the function
> being defined to be inlined.

Seems pretty ugly.  I was wondering how much it would cost to run the
index's function definition through the inliner before comparing ...
        regards, tom lane



Re: Question about simple function folding optimization

From
Peter Eisentraut
Date:
Tom Lane writes:

> But I wonder whether any better answer is possible.  I don't want to
> give up on the inlining optimization --- anyone see another fix?

If a functional index applies to the function, generate one plan with the
function inlined and one with the function call left in, and then plan
away as usual.  While that could blow up the number of plan choices to
consider (which would have to be controlled in some way), this would give
the best end results because the planner could consider the choice knowing
what the function results are used for.

-- 
Peter Eisentraut   peter_e@gmx.net



Re: Question about simple function folding optimization

From
Tom Lane
Date:
Peter Eisentraut <peter_e@gmx.net> writes:
> Tom Lane writes:
>> But I wonder whether any better answer is possible.  I don't want to
>> give up on the inlining optimization --- anyone see another fix?

> If a functional index applies to the function, generate one plan with the
> function inlined and one with the function call left in, and then plan
> away as usual.  While that could blow up the number of plan choices to
> consider (which would have to be controlled in some way), this would give
> the best end results because the planner could consider the choice knowing
> what the function results are used for.

But there isn't any situation where the non-inlined version is "better",
so there isn't really a plannable choice to be made here.  I'd be
willing to do the above if there were cases where it actually made sense
not to inline a simple function, and the planner could determine which
those were using cost estimates.  But it seems like an inappropriate
workaround for not being able to match up functions with indexes...

The urge is becoming very strong to fix this by replacing functional
indexes with expressional indexes, as I suggested doing many moons ago.
Then the difficulty at hand would be easily handled by running the
index's defining expression through eval_const_expressions before
checking if it is equal() to a candidate WHERE argument.  Not sure I
have time to do that before 7.4 though :-(
        regards, tom lane



Re: Question about simple function folding optimization

From
Tom Lane
Date:
Awhile back I said:
> [ SQL-function inlining breaks planner's ability to recognize functional
>   indexes ]

> The urge is becoming very strong to fix this by replacing functional
> indexes with expressional indexes, as I suggested doing many moons ago.
> Then the difficulty at hand would be easily handled by running the
> index's defining expression through eval_const_expressions before
> checking if it is equal() to a candidate WHERE argument.  Not sure I
> have time to do that before 7.4 though :-(

I've now done this (amazing what you can do when you're putting off
editing thousands of elog() calls ...), and so Stephan's example
works again:

regression=# explain select * from b1 where (fold_clients(a,b))='1_A';                             QUERY PLAN
----------------------------------------------------------------------Index Scan using b1ind on b1  (cost=0.00..17.12
rows=5width=36)  Index Cond: ((((a)::text || '_'::text) || upper(b)) = '1_A'::text)
 
(2 rows)

Note that EXPLAIN will show the index condition in terms of the inlined
function's expansion.  A rather interesting property of this behavior
is that the index can get matched to whether you write the original
function or its equivalent expression.
        regards, tom lane


Re: Question about simple function folding optimization

From
Bruno Wolff III
Date:
On Thu, May 29, 2003 at 13:44:18 -0400, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> 
> I've now done this (amazing what you can do when you're putting off
> editing thousands of elog() calls ...), and so Stephan's example
> works again:

Can you use functional expressions in CREATE INDEX now (7.4 CVS) as well?


Re: Question about simple function folding optimization

From
Tom Lane
Date:
Bruno Wolff III <bruno@wolff.to> writes:
> Can you use functional expressions in CREATE INDEX now (7.4 CVS) as well?

You can use expressions.  I'm not sure if you mean anything particular
by "functional expressions".  See the man page ---
http://candle.pha.pa.us/main/writings/pgsql/sgml/sql-createindex.html

(the documentation build at developer.postgresql.org doesn't seem to
have updated since before the server move :-()
        regards, tom lane


Re: Question about simple function folding optimization

From
Bruno Wolff III
Date:
On Thu, May 29, 2003 at 15:19:09 -0400, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Bruno Wolff III <bruno@wolff.to> writes:
> > Can you use functional expressions in CREATE INDEX now (7.4 CVS) as well?
> 
> You can use expressions.  I'm not sure if you mean anything particular
> by "functional expressions".  See the man page ---
> http://candle.pha.pa.us/main/writings/pgsql/sgml/sql-createindex.html
> 
> (the documentation build at developer.postgresql.org doesn't seem to
> have updated since before the server move :-()
> 
>             regards, tom lane

Thanks. I had checked the create index on developer.postgresql.org
before asking but thought that it might not be up to date.


Re: Question about simple function folding optimization

From
Peter Eisentraut
Date:
Tom Lane writes:

> (the documentation build at developer.postgresql.org doesn't seem to
> have updated since before the server move :-()

The program called "onsgmls" (or maybe "nsgmls") is missing.  Marc, can
you please install it?  It should be in a package called "opensp".

-- 
Peter Eisentraut   peter_e@gmx.net



Re: Question about simple function folding optimization

From
"Marc G. Fournier"
Date:
sorry for delay ... installing opensp right now ...


On Sun, 1 Jun 2003, Peter Eisentraut wrote:

> Tom Lane writes:
>
> > (the documentation build at developer.postgresql.org doesn't seem to
> > have updated since before the server move :-()
>
> The program called "onsgmls" (or maybe "nsgmls") is missing.  Marc, can
> you please install it?  It should be in a package called "opensp".
>
> --
> Peter Eisentraut   peter_e@gmx.net
>
>