[rt-devel] extremely slow query in rt 3.0.10 due to ILIKE instead of =

Palle Girgensohn girgen at pingpong.net
Tue Mar 30 19:30:20 EST 2004


--On tisdag, mars 30, 2004 14.46.11 -0500 Vivek Khera <vivek at khera.org> 
wrote:

>
> On Mar 30, 2004, at 2:38 PM, Jesse Vincent wrote:
>
>> What is the right way to do fast case-insensitive comparisons in
>> postgres that take database indexes into account?
>
> make your index functional on lower(column) and then compare
> lower(column) = lower('string').  don't just index on the column directly.

True. Note you should preferably compare with '=', unless you *really* need 
LIKE. ILIKE will still not use indices. lower(field)='value' will. 
lower(field) like 'value' will use index *only* if the database uses C 
locale for sorting (i.e. locale was set to `C' or unset when initdb was 
run). For RT, I guess this would be recommended, although for me it is a 
pain, since my other databases on this server need proper localized 
sorting. I guess I need to set up a separate database service for RT?

It is very strange that ILIKE does not use an index when lower() LIKE 
does...

girgen=# create index person_foo on person (lower(last_name));
girgen=# vacuum analyze person;
girgen=# explain select * from person where  lower(last_name) = 
'girgensohn';
                                 QUERY PLAN 

---------------------------------------------------------------------------
--
 Index Scan using person_foo on person  (cost=0.00..137.58 rows=78 width=96)
   Index Cond: (lower(last_name) = 'girgensohn'::text)
(2 rows)

girgen=# explain select * from person where  last_name = 'Girgensohn';
                       QUERY PLAN
---------------------------------------------------------
 Seq Scan on person  (cost=0.00..441.35 rows=4 width=96)
   Filter: (last_name = 'Girgensohn'::text)
(2 rows)

girgen=# explain select * from person where  lower(last_name) like 
'girgen%';
                                          QUERY PLAN 

---------------------------------------------------------------------------
-------------------
 Index Scan using person_foo on person  (cost=0.00..137.58 rows=78 width=96)
   Index Cond: ((lower(last_name) >= 'girgen'::text) AND (lower(last_name) 
< 'girgeo'::text))
   Filter: (lower(last_name) ~~ 'girgen%'::text)
(3 rows)

girgen=# explain select * from person where  last_name ilike 'girgen%';
                       QUERY PLAN
---------------------------------------------------------
 Seq Scan on person  (cost=0.00..441.35 rows=5 width=96)
   Filter: (last_name ~~* 'girgen%'::text)
(2 rows)


postgresql 7.4.2, freebsd 4.9 stable.

/Palle




More information about the Rt-devel mailing list