Re: From with case - Mailing list pgsql-sql
| From | Pavel Stehule |
|---|---|
| Subject | Re: From with case |
| Date | |
| Msg-id | CAFj8pRCy2r7G09dYY62zmEME9CGKhvn9U_9d7vPATO5ZGJydzA@mail.gmail.com Whole thread |
| In response to | Re: From with case (Ben Morrow <ben@morrow.me.uk>) |
| Responses |
Re: From with case
|
| List | pgsql-sql |
Hello
2013/3/26 Ben Morrow <ben@morrow.me.uk>:
> Quoth pavel.stehule@gmail.com (Pavel Stehule):
>> Dne 25.3.2013 23:51 "Ben Morrow" <ben@morrow.me.uk> napsal(a):
>> >
>> > I would use a view for this:
>> >
>> > create view vale_any as
>> > select 'P'::text "type", v.adiant, v.desc_per, v.cod
>> > from valepag v
>> > union all
>> > select 'R', v.adiant, v.desc_per, v.cod
>> > from valerec v;
>> >
>> > then
>> >
>> > for rSql in
>> > select a.adiant, a.desc_per
>> > from vale_any a
>> > where a.type = cTip and a.cod = 2
>> > loop
>>
>> This design has a performance problem. You read both tables everywhere -
>> for large tables can be bad
>
> You would think so, but, in general, Pg is cleverer than that. For the
> simple case of queries with constants in (so, a client-submitted query
> like
>
> select * from vale_any a where a.type = 'P' and a.cod = 2
>
> or the equivalent with bound placeholders) the planner won't even plan
> the parts of the view which don't get used. Try some experiments with
> EXPLAIN to see what I mean: the unused sections of the Append (that is,
> the UNION ALL) are either omitted entirely or get replaced with
>
> Result
> One-Time Filter: false
>
> (I'm not entirely sure what makes the difference, though it seems to be
> to do with how complicated the individual parts of the UNION are).
>
> PL/pgSQL is a bit more complicated, because (unless you use EXECUTE) it
> pre-plans all its statements, so the condition on a.type is not constant
> at planning time. However, if you PREPARE a statement like
>
> prepare v as select * from vale_any a
> where a.type = $1 and a.cod = $2
>
> and then run it with EXPLAIN ANALYZE EXECUTE v ('P', 2) you will see
> that although the plan includes the parts of the view that don't get
> used they are all marked '(never executed)' by EXPLAIN ANALYZE, because
> the executor had enough information to work out they could never return
> any rows. Skipping those parts of the plan at execute time does have a
> small cost--for small tables you will see the total query time go up a
> little for a prepared statement--but nothing like the cost of scanning a
> large table. I would expect it's about the same as the cost of a
> PL/pgSQL IF/THEN/ELSE.
>
> It's worth noting at this point that if you know the rows of a UNION
> will be distinct it's worth making it a UNION ALL, since otherwise Pg
> has to add a sort-and-uniq step which can be expensive.
>
> Ben
>
you have a true
CREATE OR REPLACE FUNCTION public.fo1(alfa integer)RETURNS voidLANGUAGE plpgsql
AS $function$
declare r record;
begin for r in explain select * FROM ( select 1::int as filter, * from f1 union all
select 2 as filter, * from f2) x where x.filter = alfa loop raise notice '%', r; end loop;
end;
$function$
postgres=# select fo1(1);
NOTICE: ("Append (cost=0.00..34.00 rows=2400 width=8)")
NOTICE: (" -> Seq Scan on f1 (cost=0.00..34.00 rows=2400 width=8)")fo1
-----
(1 row)
postgres=# select fo1(2);
NOTICE: ("Append (cost=0.00..34.00 rows=2400 width=8)")
NOTICE: (" -> Seq Scan on f2 (cost=0.00..34.00 rows=2400 width=8)")fo1
-----
(1 row)
In this case is postgres smart enough (Postgres 9.3)
Is strange, so this example doesn't work on 9.1. - PREPARE and EXECUTE
works with "one time filter", but plpgsql code doesn't work - it
returns nothing
Regards
Pavel Stehule