Received: from localhost (maia-5.hub.org [200.46.204.182]) by postgresql.org (Postfix) with ESMTP id BC0619FB28C for ; Mon, 2 Jul 2007 21:05:14 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.182]) (amavisd-maia, port 10024) with ESMTP id 57434-07 for ; Mon, 2 Jul 2007 21:04:50 -0300 (ADT) X-Greylist: from auto-whitelisted by SQLgrey-1.7.5 Received: from oxford.xeocode.com (unknown [87.127.95.194]) by postgresql.org (Postfix) with ESMTP id 8B6869FB283 for ; Mon, 2 Jul 2007 21:04:52 -0300 (ADT) Received: from localhost.enta.net ([127.0.0.1] helo=oxford.xeocode.com) by oxford.xeocode.com with esmtp (Exim 4.67) (envelope-from ) id 1I5Vss-0001Eu-N8; Tue, 03 Jul 2007 01:04:46 +0100 From: Gregory Stark To: "Craig James" Cc: Subject: Re: Join with lower/upper limits doesn't scale well In-Reply-To: <46898AB3.7090409@emolecules.com> (Craig James's message of "Mon, 02 Jul 2007 16:30:59 -0700") Organization: EnterpriseDB References: <46898AB3.7090409@emolecules.com> X-Draft-From: ("nnimap+mail01.enterprisedb.com:INBOX.performance" 1393) Date: Tue, 03 Jul 2007 01:04:46 +0100 Message-ID: <87hcom5p41.fsf@oxford.xeocode.com> User-Agent: Gnus/5.110006 (No Gnus v0.6) Emacs/21.4 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200707/6 X-Sequence-Number: 25690 "Craig James" writes: > Below is the explain/analyze output of the query from each database. Since > both tables are indexed on the joined columns, I don't understand why the > big table should be so much slower -- I hoped this would scale well, or at > least O(log(N)), not O(N). ... > Sort (cost=431000.85..431248.23 rows=98951 width=363) (actual time=46306.748..46417.448 rows=100000 loops=1) > Sort Key: r.row_num > -> Hash Join (cost=2583.59..422790.68 rows=98951 width=363) (actual time=469.010..45752.131 rows=100000 loops=1) > Hash Cond: ("outer".version_id = "inner".version_id) > -> Seq Scan on my_molkeys m (cost=0.00..323448.30 rows=5472530 width=363) (actual time=11.243..33299.933 rows=5472532 loops=1) > -> Hash (cost=2336.21..2336.21 rows=98951 width=8) (actual time=442.260..442.260 rows=100000 loops=1) > -> Index Scan using i_chm_rownum_row_num on my_rownum r (cost=0.00..2336.21 rows=98951 width=8) (actual time=47.551..278.736 rows=100000 loops=1) > Index Cond: ((row_num >= 100000) AND (row_num < 200000)) > Total runtime: 46543.163 ms It looks like most of the time is being spent in the sequential scan of the my_molkeys at least 33 seconds out of 46 seconds is. The actual sort is taking under a second (the hash join finishes after 45.7s and the sort finishes after 46.4s). The rest of the time (about 13s) is actually being spent in the hash join which makes me think it's overflowing work_mem and having to process the join in two batches. You might be able to speed it up by raising work_mem for this query (you can set work_mem locally using SET) The row_num where clause only narrows down the set of rows coming from the my_rownum table. If you want sublinear performance you would have to provide some way for Postgres to narrow down the rows from my_molkeys without actually having to read them all in. With the query as is the only way I can see that happening would be if you had an index on "my_molkey(version_id)" and "my_rownum(version_id) WHERE row_num between 100000 and 200000". Then it could do a merge join between two index scans. Note than even then I'm surprised the optimizer is bothering with the index for these queries, at least for the 400k case. Do you have enable_seqscan=off or random_page_cost dialled way down? -- Gregory Stark EnterpriseDB http://www.enterprisedb.com