Received: from localhost (maia-4.hub.org [200.46.204.183]) by postgresql.org (Postfix) with ESMTP id DA9E79FB446 for ; Tue, 10 Jul 2007 04:37:29 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 18196-01 for ; Tue, 10 Jul 2007 04:37:26 -0300 (ADT) X-Greylist: delayed 01:00:00.838036 by SQLgrey-1.7.5 Received: from pd2mo3so.prod.shaw.ca (shawidc-mo1.cg.shawcable.net [24.71.223.10]) by postgresql.org (Postfix) with ESMTP id 110859FB5CE for ; Tue, 10 Jul 2007 04:37:26 -0300 (ADT) Received: from pd2mr2so.prod.shaw.ca (pd2mr2so-qfe3.prod.shaw.ca [10.0.141.109]) by l-daemon (Sun ONE Messaging Server 6.0 HotFix 1.01 (built Mar 15 2004)) with ESMTP id <0JKY00N3KAEC2WE0@l-daemon> for pgsql-sql@postgresql.org; Tue, 10 Jul 2007 00:37:24 -0600 (MDT) Received: from pn2ml2so.prod.shaw.ca ([10.0.121.146]) by pd2mr2so.prod.shaw.ca (Sun Java System Messaging Server 6.2-7.05 (built Sep 5 2006)) with ESMTP id <0JKY009CKAEBW731@pd2mr2so.prod.shaw.ca> for pgsql-sql@postgresql.org; Tue, 10 Jul 2007 00:37:24 -0600 (MDT) Received: from s01060015f2cffb92.ed.shawcable.net ([68.148.106.46]) by l-daemon (Sun ONE Messaging Server 6.0 HotFix 1.01 (built Mar 15 2004)) with ESMTP id <0JKY007SQAE8LNF6@l-daemon> for pgsql-sql@postgresql.org; Tue, 10 Jul 2007 00:37:22 -0600 (MDT) Date: Tue, 10 Jul 2007 00:38:12 -0600 From: Patrick Clery Subject: Index working, but not inside function To: pgsql-sql@postgresql.org Reply-to: Patrick.Clery@gmail.com Message-id: <200707100038.15237.Patrick.Clery@gmail.com> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii Content-transfer-encoding: 7bit Content-disposition: inline User-Agent: KMail/1.9.7 X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200707/42 X-Sequence-Number: 28777 ## THE PROBLEM I'm trying to write a function that will select the ID of a row from a very large table (2M rows) using an index (places_autocomplete_idx). When I execute the function the query stalls and is apparently not taking advantage of the index. However, executing the same query outside of the function uses the index. When using a prepared statement, the planner uses the index if I use the "~=~" operator instead of the "LIKE" operator. Using a different operator within the function makes no difference whatsoever. ## THE FUNCTION CREATE OR REPLACE FUNCTION pop_country_place_id(varchar) RETURNS INTEGER AS $$ SELECT id FROM places WHERE LOWER(shortname) LIKE LOWER($1); $$ LANGUAGE sql; ## PLANNER USES INDEX WHEN "~=~" OPERATOR IS USED INSTEAD OF "LIKE" WITH PREPARED STATEMENT pop=> PREPARE pop_plan(varchar) AS SELECT id FROM places WHERE LOWER(shortname) LIKE LOWER($1::varchar); PREPARE Time: 0.295 ms pop=> pop=> EXPLAIN EXECUTE pop_plan('Canada'); QUERY PLAN --------------------------------------------------------------- Seq Scan on places (cost=0.00..214301.44 rows=12194 width=4) Filter: (lower((shortname)::text) ~~ lower(($1)::text)) (2 rows) Time: 0.310 ms pop=> DEALLOCATE pop_plan; DEALLOCATE Time: 0.131 ms pop=> PREPARE pop_plan(varchar) AS SELECT id FROM places WHERE LOWER(shortname) ~=~ LOWER($1::varchar); PREPARE Time: 0.330 ms pop=> EXPLAIN EXECUTE pop_plan('Canada'); QUERY PLAN -------------------------------------------------------------------------------------------- Bitmap Heap Scan on places (cost=375.31..38438.72 rows=12194 width=4) Recheck Cond: (lower((shortname)::text) ~=~ lower(($1)::text)) -> Bitmap Index Scan on places_autocomplete_idx (cost=0.00..372.26 rows=12194 width=0) Index Cond: (lower((shortname)::text) ~=~ lower(($1)::text)) (4 rows) Time: 0.318 ms ## PLANNER NOT USING INDEX (places_autocomplete_idx) INSIDE OF FUNCTION (TESTED WITH BOTH "~=~" AND "LIKE" OPERATORS) [sql] pop=> CREATE OR REPLACE FUNCTION pop_country_place_id(varchar) RETURNS INTEGER AS $$ pop$> SELECT id FROM places WHERE LOWER(shortname) ~=~ LOWER($1::varchar); pop$> $$ LANGUAGE sql; CREATE FUNCTION Time: 29.310 ms pop=> SELECT pop_country_place_id('United States'); * * * STALLS * * * Cancel request sent ERROR: canceling statement due to user request CONTEXT: SQL function "pop_country_place_id" statement 1 ## THE TABLE pop=> \d places Table "public.places" Column | Type | Modifiers ---------------------+------------------------+----------------------------------------------------- id | integer | not null default nextval('places_id_seq'::regclass) name | character varying(255) | permalink | character varying(255) | parent_id | integer | abreviation | character varying(3) | type | character varying(255) | is_approved | boolean | not null default false permalinks | character varying(255) | pictures_permalinks | character varying(255) | pictures_count | integer | not null default 0 region_code | character varying(2) | country_code | character varying(2) | is_active | boolean | not null default true shortname | character varying(255) | Indexes: "places_pkey" PRIMARY KEY, btree (id) "places_autocomplete_idx" btree (lower(shortname::text) varchar_pattern_ops) "places_idx_abreviation" btree (abreviation) WHERE "type"::text = 'Region'::text "places_parent_idx" btree (parent_id) "places_permalinks_idx" btree (lower(permalinks::text)) "places_pictures_permalinks_idx" btree (lower(pictures_permalinks::text)) "places_region_idx" btree (country_code, region_code) WHERE "type"::text = 'Region'::text "regions_idx" btree (country_code, region_code) WHERE "type"::text = 'Region'::text Foreign-key constraints: "places_regions_fkey" FOREIGN KEY (country_code, region_code) REFERENCES regions(country_code, region_code) ON UPDATE CASCADE