Received: from localhost (unknown [200.46.204.182]) by postgresql.org (Postfix) with ESMTP id 418FD2E31F8 for ; Sun, 20 Jan 2008 10:36:02 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.182]) (amavisd-maia, port 10024) with ESMTP id 15107-07 for ; Sun, 20 Jan 2008 10:35:40 -0400 (AST) Received: from mail01.enterprisedb.com (mail01.enterprisedb.com [63.246.7.168]) by postgresql.org (Postfix) with ESMTP id 181872E31F1 for ; Sun, 20 Jan 2008 10:35:56 -0400 (AST) thread-index: AchbcdXm9Tc+lA6rTZy+sD49NcRxdw== Received: from [192.168.1.33] ([81.110.31.243]) by mail01.enterprisedb.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Sun, 20 Jan 2008 09:36:25 -0500 Message-ID: <47935C0C.4090908@enterprisedb.com> Content-Class: urn:content-classes:message Importance: normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.4133 Date: Sun, 20 Jan 2008 14:34:52 +0000 From: "Heikki Linnakangas" User-Agent: Icedove 1.5.0.14pre (X11/20071020) MIME-Version: 1.0 To: "Dean Rasheed" Cc: Subject: Re: Slow set-returning functions References: In-Reply-To: Content-Type: text/plain; format=flowed; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 20 Jan 2008 14:36:25.0703 (UTC) FILETIME=[D5D57F70:01C85B71] X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200801/153 X-Sequence-Number: 28392 Dean Rasheed wrote: > I have been having difficulty with some functions which return sets of > rows. The functions seem to run very slowly, even though the queries > they run execute very quicky if I run them directly from psgl. > Typically these queries are only returning a few hundred rows with my > real data. > > I have had difficulty coming up with a simple test case, but the code > below usually shows the same problem. Sometimes I have to run the > setup code a few times before it happens - not sure why (I would > expect this to be deterministic), but perhaps there is some randomness > introduced by the sampling done by the analyse. > > The function foo() which has a hard-coded LIMIT always executes > quickly (comparable to running the query directly). > > However, the function foo(int) which is passed the same LIMIT as a > parameter executes around 30 times slower. The only difference is that > the LIMIT is a parameter to the function, although the LIMIT isn't > reached anyway in this case. Sometimes running this same script > generates data for which this function executes as fast as the other > one (which is always fast). This is clearly because the planner doesn't know what the value for the parameter will be at run time, so it chooses a plan that's not optimal for LIMIT 100. > Is there any way that I can see what execution plan is being used > internally by the functions? Not directly, but you can do this: postgres=# PREPARE p (int4) AS SELECT id FROM foo WHERE lower(name) LIKE 'foo' ORDER BY id OFFSET 0 LIMIT $1; PREPARE postgres=# EXPLAIN EXECUTE p(100); QUERY PLAN ----------------------------------------------------------------------------- Limit (cost=0.00..49.18 rows=2 width=4) -> Index Scan using foo_pkey on foo (cost=0.00..614.77 rows=25 width=4) Filter: (lower(name) ~~ 'foo'::text) (3 rows) You could work around that by using EXECUTE in the plpgsql function, to force the query to be planned on every execution with the actual value of the LIMIT. -- Heikki Linnakangas EnterpriseDB http://www.enterprisedb.com