Received: from localhost (maia-2.hub.org [200.46.204.187]) by postgresql.org (Postfix) with ESMTP id 7193A9FA0CC for ; Tue, 19 Dec 2006 14:23:19 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.187]) (amavisd-new, port 10024) with ESMTP id 17692-08 for ; Tue, 19 Dec 2006 14:23:11 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey-1.7.4 Received: from mail.metronet.co.uk (mail.metronet.co.uk [213.162.97.75]) by postgresql.org (Postfix) with ESMTP id 7EA439F9C35 for ; Tue, 19 Dec 2006 14:23:12 -0400 (AST) Received: from mainbox.archonet.com (84-51-143-99.archon037.adsl.metronet.co.uk [84.51.143.99]) by smtp.metronet.co.uk (MetroNet Mail) with ESMTP id 555DA73EB1; Tue, 19 Dec 2006 18:23:06 +0000 (GMT) Received: from [192.168.1.17] (client17.office.archonet.com [192.168.1.17]) by mainbox.archonet.com (Postfix) with ESMTP id 95FBBFF04; Tue, 19 Dec 2006 18:23:06 +0000 (GMT) Message-ID: <45882E0A.8070807@archonet.com> Date: Tue, 19 Dec 2006 18:23:06 +0000 From: Richard Huxton User-Agent: Thunderbird 1.5.0.8 (X11/20061115) MIME-Version: 1.0 To: Jeremy Haile Cc: pgsql-performance@postgresql.org Subject: Re: Inner join vs where-clause subquery References: <1166538737.31684.281175363@webmail.messagingengine.com> <458813ED.50108@archonet.com> <1166549705.21302.281208465@webmail.messagingengine.com> In-Reply-To: <1166549705.21302.281208465@webmail.messagingengine.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200612/478 X-Sequence-Number: 22534 Jeremy Haile wrote: > Here is the explain analyze output: Well, the row estimates are about as far out as you can get: > -> Index Scan using activity_log_facts_pkey on > activity_log_facts (cost=0.00..1831613.82 rows=1539298 > width=12) (actual time=0.050..0.050 rows=0 loops=1) > -> Index Scan Backward using activity_log_facts_pkey on > activity_log_facts (cost=0.00..1831613.82 rows=1539298 > width=12) (actual time=0.004..0.004 rows=0 loops=1) > -> Index Scan using activity_log_facts_dtcreatedate_idx on > activity_log_facts (cost=0.00..5406927.50 rows=1539298 > width=12) (actual time=100221.953..100221.953 rows=0 loops=1) > -> Index Scan Backward using > activity_log_facts_dtcreatedate_idx on activity_log_facts > (cost=0.00..5406927.50 rows=1539298 width=12) (actual > time=56367.364..56367.364 rows=0 loops=1) Hmm - it's using the indexes on dtCreateDate and nlogid which seems broadly sensible, and then plans to limit the results for min()/max(). However, it's clearly wrong about how many rows will satisfy nlogid > (select max(a.end_nlogid) from activity_log_import_history a) >>> select min(nlogid) as start_nlogid, >>> max(nlogid) as end_nlogid, >>> min(dtCreateDate) as start_transaction_timestamp, >>> max(dtCreateDate) as end_transaction_timestamp >>> from activity_log_facts >>> where nlogid > ( select max(a.end_nlogid) from >>> activity_log_import_history a) >>> and dtCreateDate < '2006-12-18 9:10' If you run explain on the other forms of your query, I'd guess it's much more accurate. There's a simple way to see if that is the issue. Run the sub-query and substitute the actual value returned into the query above. Then, try the same but with a prepared query. If it's down to nlogid estimates then the first should be fast and the second slow. -- Richard Huxton Archonet Ltd