Received: from maia.hub.org (maia-5.hub.org [200.46.204.29]) by mail.postgresql.org (Postfix) with ESMTP id 41A3E1337B54 for ; Mon, 11 Apr 2011 18:11:08 -0300 (ADT) 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 99850-03 for ; Mon, 11 Apr 2011 21:10:57 +0000 (UTC) X-Greylist: delayed 00:50:58.234685 by SQLgrey-1.7.6 Received: from server134.penguinhost.net (server134.penguinhost.net [69.65.27.134]) by mail.postgresql.org (Postfix) with ESMTP id B58121337C55 for ; Mon, 11 Apr 2011 18:03:01 -0300 (ADT) Received: from [127.0.0.1] (helo=server139.advancednetworkhosting.com) by server134.penguinhost.net with esmtpa (Exim 4.69) (envelope-from ) id 1Q9NSr-0005Lw-56 for pgsql-performance@postgresql.org; Mon, 11 Apr 2011 15:12:01 -0500 Received: from [192.168.121.100] ([76.105.146.213] helo=[192.168.121.100]) with IPv4:25 by server139.advancednetworkhosting.com; 11 Apr 2011 15:12:00 -0500 Message-ID: Date: Mon, 11 Apr 2011 13:11:58 -0700 From: Lucas Madar User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.14) Gecko/20110223 Lightning/1.0b2 Thunderbird/3.1.8 MIME-Version: 1.0 To: pgsql-performance@postgresql.org Subject: Poor performance when joining against inherited tables Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Assp-ID: server139.advancednetworkhosting.com () X-Assp-Version: 1.7.1.3(1.0.2) X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server134.penguinhost.net X-AntiAbuse: Original Domain - postgresql.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - samsix.com X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.585 tagged_above=-10 required=5 tests=BAYES_00=-1.9, SARE_MILLIONSOF=0.315 X-Spam-Level: X-Archive-Number: 201104/142 X-Sequence-Number: 43204 I have a database that contains many tables, each with some common characteristics. For legacy reasons, they have to be implemented in a way so that they are *all* searchable by an older identifier to find the newer identifier. To do this, we've used table inheritance. Each entry has an id, as well as a legacyid1 and legacyid2. There's a master table that the application uses, containing a base representation and common characteristics: objects ( id, ... ) item ( id, legacyid1, legacyid2 ) | - itemXX | - itemYY There is nothing at all in the item table, it's just used for inheritance. However, weird things happen when this table is joined: EXPLAIN ANALYZE SELECT * FROM objects INNER JOIN item f USING ( id ); QUERY PLAN ------------ Hash Join (cost=457943.85..1185186.17 rows=8643757 width=506) Hash Cond: (f.id = objects.id) -> Append (cost=0.00..224458.57 rows=8643757 width=20) -> Seq Scan on item f (cost=0.00..26.30 rows=1630 width=20) -> Seq Scan on itemXX f (cost=0.00..1.90 rows=90 width=20) -> Seq Scan on itemYY f (cost=0.00..7.66 rows=266 width=20) -> Seq Scan on itemZZ f (cost=0.00..1.02 rows=2 width=20) ... -> Hash (cost=158447.49..158447.49 rows=3941949 width=490) -> Seq Scan on objects (cost=0.00..158447.49 rows=3941949 width=490) This scans everything over everything, and obviously takes forever (there are millions of rows in the objects table, and tens of thousands in each itemXX table). However, if I disable seqscan (set enable_seqscan=false), I get the following plan: QUERY PLAN ------------ Hash Join (cost=10001298843.53..290002337961.71 rows=8643757 width=506) Hash Cond: (f.id = objects.id) -> Append (cost=10000000000.00..290000536334.43 rows=8643757 width=20) -> Seq Scan on item f (cost=10000000000.00..10000000026.30 rows=1630 width=20) -> Index Scan using xxx_pkey on itemXX f (cost=0.00..10.60 rows=90 width=20) -> Index Scan using yyy_pkey on itemYY f (cost=0.00..25.24 rows=266 width=20) -> Index Scan using zzz_pkey on itemZZ f (cost=0.00..9.28 rows=2 width=20) ... -> Hash (cost=999347.17..999347.17 rows=3941949 width=490) -> Index Scan using objects_pkey on objects (cost=0.00..999347.17 rows=3941949 width=490) This seems like a much more sensible query plan. But it seems to think doing a sequential scan on the *empty* item table is excessively expensive in this case. Aside from enable_seqscan=false, is there any way I can make the query planner not balk over doing a seqscan on an empty table? Thanks, Lucas Madar