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

From Phil Frost
Subject optimizing constant quals within outer joins
Date
Msg-id 20060628143536.GA11399@unununium.org
Whole thread Raw
Responses Re: optimizing constant quals within outer joins  (Martijn van Oosterhout <kleptog@svana.org>)
Re: optimizing constant quals within outer joins  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-hackers
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.

In some cases, the planner already optimizes this by moving the "where
i_have_global_priv(n)" qualification out of the seq scan filter and into
the one-time filter of a result node. The relevant function in the code
seems to be pull_constant_clauses, called from query_planner in
planmain.c around line 118.

By experimentation, it seems that this optimization will not be made on
either side of an outer join. For example:

dew=# explain select * from   (select * from private.orderitem where i_have_global_priv(28)) as oi   join (
select* from private.orderitemproduct where i_have_global_priv(32)   ) as oip using (objectid);
           QUERY PLAN                                       
 
---------------------------------------------------------------------------------------Result  (cost=96.56..402.70
rows=5004width=325)  One-Time Filter: (i_have_global_priv(28) AND i_have_global_priv(32))  ->  Hash Join
(cost=96.55..402.69rows=5004 width=325)        Hash Cond: ("outer".objectid = "inner".objectid)        ->  Seq Scan on
orderitem (cost=0.00..165.44 rows=6044 width=306)        ->  Hash  (cost=84.04..84.04 rows=5004 width=23)
-> Seq Scan on orderitemproduct  (cost=0.00..84.04 rows=5004 width=23)
 

dew=# explain select * from   (select * from private.orderitem where i_have_global_priv(28)) as oi   left join (
select* from private.orderitemproduct where i_have_global_priv(32)   ) as oip using (objectid);
        QUERY PLAN                                    
 
---------------------------------------------------------------------------------Hash Left Join  (cost=100.72..301.94
rows=2015width=325)  Hash Cond: ("outer".objectid = "inner".objectid)  ->  Seq Scan on orderitem  (cost=0.00..180.55
rows=2015width=306)        Filter: i_have_global_priv(28)  ->  Hash  (cost=96.55..96.55 rows=1668 width=23)        ->
SeqScan on orderitemproduct  (cost=0.00..96.55 rows=1668 width=23)              Filter: i_have_global_priv(32)
 


Notice that the cross join plan results in i_have_global_priv being
called just twice -- once for each privilege being checked, while the
left join plan will result in it being called once for each row.

So, is this something I can coerce someone into doing? It would be very
much appreciated here.


[1] <http://veil.projects.postgresql.org/>


pgsql-hackers by date:

Previous
From: Martijn van Oosterhout
Date:
Subject: Re: Help with casting and comparing.
Next
From: Martijn van Oosterhout
Date:
Subject: Re: optimizing constant quals within outer joins