Received: from maia.hub.org (maia-2.hub.org [200.46.204.251]) by mail.postgresql.org (Postfix) with ESMTP id CBBC61337C33 for ; Tue, 30 Nov 2010 14:19:16 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.251]) (amavisd-maia, port 10024) with ESMTP id 87386-01-10 for ; Tue, 30 Nov 2010 18:19:09 +0000 (UTC) Received: from news.hub.org (news.hub.org [200.46.204.72]) by mail.postgresql.org (Postfix) with ESMTP id 2D1F71337C57 for ; Tue, 30 Nov 2010 14:12:41 -0400 (AST) Received: from news.hub.org (news.hub.org [200.46.204.72]) by news.hub.org (8.14.4/8.14.4) with ESMTP id oAUICetR005656 for ; Tue, 30 Nov 2010 14:12:40 -0400 (AST) (envelope-from news@news.hub.org) Received: (from news@localhost) by news.hub.org (8.14.4/8.14.4/Submit) id oAUHhPqg015117 for pgsql-performance@postgresql.org; Tue, 30 Nov 2010 13:43:25 -0400 (AST) (envelope-from news) From: "T.H." X-Newsgroups: pgsql.performance Subject: Question about subselect/IN performance Date: Tue, 30 Nov 2010 12:43:24 -0500 Organization: Hub.Org Networking Services Lines: 40 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Complaints-To: usenet@news.hub.org User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2.9) Gecko/20100915 Lightning/1.0b2 Thunderbird/3.1.4 To: pgsql-performance@postgresql.org X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.91 tagged_above=-10 required=5 tests=BAYES_00=-1.9, T_RP_MATCHES_RCVD=-0.01 X-Spam-Level: X-Archive-Number: 201011/415 X-Sequence-Number: 41439 I have a query that's running an IN/Subselect that joins three different tables and gets a list of IDs to compare against... the subselect basically looks for records through a join table based on the 3rd table's name, similar to: ... IN (SELECT id FROM foo, foo_bar, bar WHERE foo.id = foo_bar.foo_id AND bar.id = foo_bar.bar_id AND bar.name = "something") ... This is all nested in a fairly complex query, and several of these subselects operate on different tables within the query. The whole thing, on some high-cardinality cases, can take 2.5 seconds to run (clearly something can be done about that). So in this example, the cardinality of the bar table is very low, and fairly constant, something on the order of 5-7 records. In an optimization attempt, I reduced the joins in the subselect from 2 to 1 by passing in the ID of the bar with the correct name, which I can easily cache application-side or pre-fetch in a single query. Now it looks like this: ... IN (SELECT id FROM foo, foo_bar WHERE foo.id = foo_bar.foo_id AND foo_bar.bar_id = 1) ... Crazy thing is, that single optimization reduced the query time significantly, from 2.5-3 seconds down to 40-60ms. Does anyone have any kind of explanation for this? Are the inner workings of the IN clause taking the plan for the subselect into account when running, and doing something clever with it? Any insight on the internal mechanisms of IN or subselects in Postgres would be greatly appreciated if anyone knows more. Also, are there any better ways you can think of doing such an IN query, using non-subselect means that might be more efficient? Thanks in advance, any advice/help understanding this better is greatly appreciated.