Re: SQL Function performance - Mailing list pgsql-performance

From Jim C. Nasby
Subject Re: SQL Function performance
Date
Msg-id 20051004205225.GX40138@pervasive.com
Whole thread Raw
In response to SQL Function performance  (<adnandursun@asrinbilisim.com.tr>)
List pgsql-performance
On Thu, Sep 29, 2005 at 10:54:58PM +0300, adnandursun@asrinbilisim.com.tr wrote:
> Hi All,
>
>         I have a SQL function like :
>
> CREATE OR REPLACE FUNCTION
> fn_get_yetkili_inisyer_listesi(int4, int4)
>   RETURNS SETOF kod_adi_liste_type AS
> $BODY$
>  SELECT Y.KOD,Y.ADI
>    FROM T_YER Y
>   WHERE EXISTS (SELECT 1
>     FROM T_GUZER G
>           WHERE (G.BIN_YER_KOD = $1 OR COALESCE($1,0)=0)
>      AND FN_FIRMA_ISVISIBLE(G.FIRMA_NO,$2) = 1
>      AND G.IN_YER_KOD = Y.KOD)
>     AND Y.IPTAL = 'H';
> $BODY$
>   LANGUAGE 'sql' VOLATILE;
>
>     When i use like "SELECT * FROM
> fn_get_yetkili_inisyer_listesi(1, 3474)" and
> planner result is  "Function Scan on
> fn_get_yetkili_inisyer_listesi  (cost=0.00..12.50 rows=1000
> width=36) (1 row) " and it runs very slow.
>
>     But when i use like
>
>     "SELECT Y.KOD,Y.ADI
>          FROM T_YER Y
>        WHERE EXISTS (SELECT 1
>                                         FROM T_GUZER G
>                                       WHERE (G.BIN_YER_KOD
> = 1 OR COALESCE(1,0)=0)
>      AND FN_FIRMA_ISVISIBLE(G.FIRMA_NO,3474) = 1
>      AND G.IN_YER_KOD = Y.KOD)
>      AND Y.IPTAL = 'H';"
>
> planner result :
>
> "
>                                                  QUERY PLAN
>
> --------------------------------------------------------------------------------
> -----------------------------
>  Seq Scan on t_yer y  (cost=0.00..3307.79 rows=58 width=14)
>    Filter: (((iptal)::text = 'H'::text) AND (subplan))
>    SubPlan
>      ->  Index Scan using
> t_guzer_ucret_giris_performans_idx on t_guzer g  (cost
> =0.00..28.73 rows=1 width=0)
>            Index Cond: ((bin_yer_kod = 1) AND (in_yer_kod =
> $0))
>            Filter: (fn_firma_isvisible(firma_no, 3474) = 1)
> (6 rows)
> "
>   and it runs very fast.
>
> Any idea ?

Need EXPLAIN ANALYZE.

I suspect this is due to a cached query plan. PostgreSQL will cache a
query plan for the SELECT the first time you run the function and that
plan will be re-used. Depending on what data you call the function with,
you could get a very different plan.

Also, you might do better with a JOIN instead of using EXISTS.  You can
also make this function STABLE instead of VOLATILE. Likewise, if
FN_FIRMA_ISVISIBLE can't change any data, you can also make it STABLE
which would likely improve the performance of the query. But neither of
these ideas would account for the difference between function
performance and raw query performance.

On a side note, if OR $1 IS NULL works that will be more readable (and
probably faster) than the OR COALESCE($1,0)=0.
--
Jim C. Nasby, Sr. Engineering Consultant      jnasby@pervasive.com
Pervasive Software      http://pervasive.com    work: 512-231-6117
vcard: http://jim.nasby.net/pervasive.vcf       cell: 512-569-9461

pgsql-performance by date:

Previous
From: Joe
Date:
Subject: Re: Comparative performance
Next
From: "Jim C. Nasby"
Date:
Subject: Re: SELECT LIMIT 1 VIEW Performance Issue