Received: from maia.hub.org (maia-5.hub.org [200.46.204.29]) by mail.postgresql.org (Postfix) with ESMTP id 6E1BC13364DE for ; Mon, 17 Jan 2011 16:24:40 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.29]) (amavisd-maia, port 10024) with ESMTP id 87772-08 for ; Mon, 17 Jan 2011 20:24:33 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from sss.pgh.pa.us (sss.pgh.pa.us [66.207.139.130]) by mail.postgresql.org (Postfix) with ESMTP id 0E4BB133616B for ; Mon, 17 Jan 2011 16:24:30 -0400 (AST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss.pgh.pa.us (8.14.2/8.14.2) with ESMTP id p0HKOQVF020066; Mon, 17 Jan 2011 15:24:27 -0500 (EST) To: Jeremy Palmer cc: "pgsql-performance@postgresql.org" Subject: Re: Possible to improve query plan? In-reply-to: <666FB8D75E95AE42965A0E76A5E5337E06D2C683BF@prdlsmmsg01.ad.linz.govt.nz> References: <666FB8D75E95AE42965A0E76A5E5337E06D2C683BF@prdlsmmsg01.ad.linz.govt.nz> Comments: In-reply-to Jeremy Palmer message dated "Mon, 17 Jan 2011 16:21:56 +1300" Date: Mon, 17 Jan 2011 15:24:26 -0500 Message-ID: <20065.1295295866@sss.pgh.pa.us> From: Tom Lane 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: 201101/136 X-Sequence-Number: 41923 Jeremy Palmer writes: > I've come to a dead end in trying to get a commonly used query to > perform better. > EXPLAIN > SELECT * FROM ( > SELECT > row_number() OVER (PARTITION BY id ORDER BY _revision_created DESC) as row_number, > * > FROM > version_crs_coordinate_revision > WHERE ( > (_revision_created <= 16 AND _revision_expired > 16 AND _revision_expired <= 40) OR > (_revision_created > 16 AND _revision_created <= 40) > ) > ) AS T > WHERE row_number = 1; If I'm not mistaken, that's a DB2-ish locution for a query with DISTINCT ON, ie, you're looking for the row with highest _revision_created for each value of id. It might perform well on DB2, but it's going to mostly suck on Postgres --- we don't optimize window-function queries very much at all at the moment. Try writing it with DISTINCT ON instead of a window function, like so: SELECT DISTINCT ON (id) * FROM version_crs_coordinate_revision WHERE ( (_revision_created <= 16 AND _revision_expired > 16 AND _revision_expired <= 40) OR (_revision_created > 16 AND _revision_created <= 40) ) ORDER BY id, _revision_created DESC; You could also experiment with various forms of GROUP BY if you're loath to use any Postgres-specific syntax. regards, tom lane