Re: optimizing constant quals within outer joins - Mailing list pgsql-hackers

From Phil Frost
Subject Re: optimizing constant quals within outer joins
Date
Msg-id 20060628152424.GA23509@unununium.org
Whole thread Raw
In response to Re: optimizing constant quals within outer joins  (Martijn van Oosterhout <kleptog@svana.org>)
Responses Re: optimizing constant quals within outer joins
List pgsql-hackers
On Wed, Jun 28, 2006 at 05:11:59PM +0200, Martijn van Oosterhout wrote:
> On Wed, Jun 28, 2006 at 10:35:37AM -0400, Phil Frost wrote:
> > I have an optimization I'd like to see which I think should be pretty
> > easy for someone familiar with the planner code to implement. My
> > situation is this: I have an application using veil[1]. Essentially, I
> > have a schema "private" and another "public". Private contains regular
> > tables, where private contains views on those tables, like "create view
> > public.foo as select * from foo where i_have_global_priv('select_foo')",
> > and i_have_global_priv is a stable function.
> > 
> > My problem is that in several situations, postgresql is planning a
> > sequential scan with i_have_global_priv(n) as a filter, where N is some
> > constant literal specified in the view definition. This leads to the
> > function being called hundreds of thousands of times, which makes my
> > query orders of magnitude slower.
> 
> Is the function marked stable or immutable?
> 
> In the examples you give the planner can't move the function around the
> tree because that would change the output of the query. For inner joins
> it's ok, for outer joins it's much more tricky.
> 
> I thought the planner would evaluate constant conditions early on which
> I why I'm asking about the function.

i_have_global_priv is a stable function.

The planner in fact can move the function around without changing the
output. I can make it do so by putting "offset 0" in the subqueries:

dew=# explain select * from   (select * from private.orderitem where i_have_global_priv(28) offset 0) as oi   left join
(      select * from private.orderitemproduct where i_have_global_priv(32) offset 0   ) as oip using (objectid);
                                  QUERY PLAN                                             
 
---------------------------------------------------------------------------------------------------Merge Right Join
(cost=1310.33..3603.67rows=151221 width=187)  Merge Cond: ("outer".objectid = "inner".objectid)  ->  Sort
(cost=441.55..454.06rows=5004 width=45)        Sort Key: oip.objectid        ->  Subquery Scan oip  (cost=0.00..134.08
rows=5004width=45)              ->  Limit  (cost=0.00..84.04 rows=5004 width=23)                    ->  Result
(cost=0.00..84.04rows=5004 width=23)                          One-Time Filter: i_have_global_priv(32)
      ->  Seq Scan on orderitemproduct  (cost=0.00..84.04 rows=5004 width=23)  ->  Sort  (cost=868.78..883.89 rows=6044
width=146)       Sort Key: oi.objectid        ->  Limit  (cost=0.00..165.44 rows=6044 width=306)              ->
Result (cost=0.00..165.44 rows=6044 width=306)                    One-Time Filter: i_have_global_priv(28)
    ->  Seq Scan on orderitem  (cost=0.00..165.44 rows=6044 width=306)
 

The transformation is from this:
  ->  Seq Scan on orderitem  (cost=0.00..180.55 rows=2015 width=306)        Filter: i_have_global_priv(28)

to this:
  ->  Result  (cost=0.00..165.44 rows=6044 width=306)        One-Time Filter: i_have_global_priv(28)        ->  Seq
Scanon orderitem  (cost=0.00..165.44 rows=6044 width=306)
 

which produce the same result. However, I'm not about to put "offset 0"
in all my view definitions, as that would prevent a number of other
extremely desirable optimizations.

Can a Result node not be an input to an outer join node? That would make
me sad :(


pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: Help with casting and comparing.
Next
From: Tom Lane
Date:
Subject: Re: optimizing constant quals within outer joins