Received: from localhost (unknown [200.46.208.211]) by mail.postgresql.org (Postfix) with ESMTP id 8A1F563375F for ; Sat, 9 Jan 2010 08:46:20 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by localhost (mx1.hub.org [200.46.208.211]) (amavisd-maia, port 10024) with ESMTP id 76283-07 for ; Sat, 9 Jan 2010 12:46:02 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from ppsw-5.csi.cam.ac.uk (ppsw-5.csi.cam.ac.uk [131.111.8.135]) by mail.postgresql.org (Postfix) with ESMTP id 8B7E96336F9 for ; Sat, 9 Jan 2010 08:46:09 -0400 (AST) X-Cam-AntiVirus: no malware found X-Cam-SpamDetails: not scanned X-Cam-ScannerInfo: http://www.cam.ac.uk/cs/email/scanner/ Received: from pip.srcf.societies.cam.ac.uk ([131.111.179.83]:54781 helo=[127.0.0.1]) by ppsw-5.csi.cam.ac.uk (ppsw.cam.ac.uk [131.111.8.135]:25) with esmtp id 1NTahj-0003it-IR (Exim 4.70) for pgsql-performance@postgresql.org (return-path ); Sat, 09 Jan 2010 12:46:07 +0000 Message-ID: <4B487A8F.6000003@cam.ac.uk> Date: Sat, 09 Jan 2010 12:46:07 +0000 From: Richard Neill Organization: RUO3.org User-Agent: Thunderbird 2.0.0.22 (X11/20090608) MIME-Version: 1.0 To: pgsql-performance@postgresql.org Subject: Joint index including MAX() ? Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.181 tagged_above=-10 required=5 tests=AWL=1.418, BAYES_00=-2.599 X-Spam-Level: X-Archive-Number: 201001/162 X-Sequence-Number: 37042 Dear All, I'm trying to optimise the speed of some selects with the where condition: WHERE id = (SELECT MAX(id) FROM tbl_sort_report WHERE parcel_id_code='43024') This is relatively slow, taking about 15-20ms, even though I have a joint index on both fields: CREATE INDEX testidx3 ON tbl_sort_report (id, parcel_id_code); So, my question is, is there any way to improve this? I'd expect that an index on ( max(id),parcel_id_code ) would be ideal, excepting that postgres won't allow that (and such an index probably doesn't make much conceptual sense). Explain Analyze is below. Thanks, Richard Here is part of the schema. id is the primary key; parcel_id_code loops from 0...99999 and back again every few hours. fsc_log=> \d tbl_sort_report Table "public.tbl_sort_report" Column | Type | Modifiers ----------------------+--------------------------+----------------------------------------------------- id | bigint | not null default nextval('master_id_seq'::regclass) timestamp | timestamp with time zone | parcel_id_code | integer | (etc) EXPLAIN ANALYZE (SELECT MAX(id) FROM tbl_sort_report WHERE parcel_id_code='43024'); QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- Result (cost=7.34..7.35 rows=1 width=0) (actual time=17.712..17.714 rows=1 loops=1) InitPlan 1 (returns $0) -> Limit (cost=0.00..7.34 rows=1 width=8) (actual time=17.705..17.705 rows=0 loops=1) -> Index Scan Backward using testidx3 on tbl_sort_report (cost=0.00..14.67 rows=2 width=8) (actual time=17.700..17.700 rows=0 loops=1) Index Cond: (parcel_id_code = 43024) Filter: (id IS NOT NULL) Total runtime: 17.786 ms