Thread: plpgsql and index usage

plpgsql and index usage

From
Ryan Mahoney
Date:
The following statements do not utilize an index when executed inside a
plpgsql procedure, but does when executed interactively in psql!

Does not use index:

FOR somemorerows IN SELECT zipcode_list FROM pa_zipcode_proximityWHERE zipcode = zipcode_inAND proximity <=
proximity_range_in
LOOPzipcodes := zipcodes || '','' || somemorerows.zipcode_list;
END LOOP;

However:SELECT zipcode_list FROM pa_zipcode_proximityWHERE zipcode = zipcode_inAND proximity <= proximity_range_in;

Does use the index!  zipcode_list and zipcode are text, proximity is an
integer.  There is a primary key on zipcode and proximity.  We are using
PostgreSQL 7.3 on i686-pc-linux-gnu, compiled by GCC 2.96.  Any ideas? 
We have recently done a vacuum full and analyze.

Any help is much appreciated!

-r
-- 
Ryan Mahoney
ryan@flowlabs.com
(718)721-8790

"Tomorrow's Company. Today's Budget."            http://www.flowlabs.com



Re: plpgsql and index usage

From
Tom Lane
Date:
Ryan Mahoney <ryan@flowlabs.com> writes:
> The following statements do not utilize an index when executed inside a
> plpgsql procedure, but does when executed interactively in psql!

I suspect you are not telling the full truth here.

> However:
>  SELECT zipcode_list 
>  FROM pa_zipcode_proximity
>  WHERE zipcode = zipcode_in
>  AND proximity <= proximity_range_in;
> Does use the index!

Where are zipcode_in and proximity_range_in coming from?  Did you
actually type the statement just like that, or are there really
constants there?

I suspect that you're seeing the difference between what the planner
does when it can see a constant comparison value and what it has to do
when it sees a plpgsql variable as the comparison value --- it has to
use default selectivity estimates in the latter case.  But it's hard to
say more without a lot more info.  In particular I'd like to know what
you *really* typed, what EXPLAIN output you get, and what the pg_stats
rows for zipcode and proximity contain ...
        regards, tom lane


Re: plpgsql and index usage

From
Tom Lane
Date:
Ryan Mahoney <ryan@flowlabs.com> writes:
>  Index Scan using pa_zipcode_proximity_pk on pa_zipcode_proximity  (cost=
> 0.00..13.53 rows=3 width=862)
>    Index Cond: ((zipcode = '11103'::bpchar) AND (proximity <= 100))
> (183 rows)

Hmm ... evidently zipcode is declared as type char(5) (note the "bpchar"
coercion).  Is the plpgsql variable it's being compared to declared the
same way?  This could be ye olde cross-datatype-coercion problem.
        regards, tom lane


Re: plpgsql and index usage

From
Ryan Mahoney
Date:
>Ryan Mahoney <ryan@flowlabs.com> writes:
>>  Index Scan using pa_zipcode_proximity_pk on pa_zipcode_proximity  (cost=
>> 0.00..13.53 rows=3 width=862)
>>    Index Cond: ((zipcode = '11103'::bpchar) AND (proximity <= 100))
>> (183 rows)
>
>Hmm ... evidently zipcode is declared as type char(5) (note the "bpchar"
>coercion).  Is the plpgsql variable it's being compared to declared the
>same way?  This could be ye olde cross-datatype-coercion problem.

Interesting!  I think in plpgsql the data type of the argument coming
in to the function is "text".  Are you suggesting that I:a. use a different datatype in plpgsql or b. cast the values
orc.change the data type in the table
 

I am not familiar with the bpchar type, but I am looking into it now.

Thanks!

-r


Re: plpgsql and index usage

From
Tom Lane
Date:
Ryan Mahoney <ryan@flowlabs.com> writes:
>> Hmm ... evidently zipcode is declared as type char(5) (note the "bpchar"
>> coercion).  Is the plpgsql variable it's being compared to declared the
>> same way?  This could be ye olde cross-datatype-coercion problem.

> Interesting!  I think in plpgsql the data type of the argument coming
> in to the function is "text".

Bingo.

>  Are you suggesting that I:
>     a. use a different datatype in plpgsql or 
>     b. cast the values or
>     c. change the data type in the table

Yes ;-).  Presumably (b) would be the least painful route, but any of
these would do the trick.

> I am not familiar with the bpchar type, but I am looking into it now.

Internal name for char(n).
        regards, tom lane


Re: plpgsql and index usage

From
Ryan Mahoney
Date:
>>  Are you suggesting that I:
>>     a. use a different datatype in plpgsql or 
>>     b. cast the values or
>>     c. change the data type in the table
>
>Yes ;-).  Presumably (b) would be the least painful route, but any of
>these would do the trick.

It turns out that the text and char(5) were not the problem - it was
an integer field that was passed into the function as a text (the
proximity field)!  It now utilizes the index and has gone from taking
over 7 seconds to complete to .011 seconds!

I love postgres!

Thanks Tom!

-r