Received: from maia.hub.org (maia-2.hub.org [200.46.204.251]) by mail.postgresql.org (Postfix) with ESMTP id E99A51337C07 for ; Wed, 11 May 2011 13:39:10 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.251]) (amavisd-maia, port 10024) with ESMTP id 62375-07 for ; Wed, 11 May 2011 16:39:03 +0000 (UTC) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.6 Received: from mail-bw0-f46.google.com (mail-bw0-f46.google.com [209.85.214.46]) by mail.postgresql.org (Postfix) with ESMTP id 2A5351337C5B for ; Wed, 11 May 2011 13:38:45 -0300 (ADT) Received: by bwz15 with SMTP id 15so589491bwz.19 for ; Wed, 11 May 2011 09:38:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:in-reply-to:references:date :message-id:subject:from:to:cc:content-type :content-transfer-encoding; bh=pz7B+GmpqwsAX5gpDRQDPv0baTpXh7s5XUW5lertq8k=; b=mJjd891231QdP5YSf+LXNAVx+jaB7g4/KX6jVQYWDG3Qi8yYX/vHkzNmbWoaqgbyrT 1ZfiSSp3o3kpohuk+czI3zb5tWvTYGMXNWDBAlRXDJ0ArwoRRIlpF/jnZkVlYn9i23E3 dWaOPxAcY5XzHFIBy7IZWjEufSc0ZX48wuDOY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type:content-transfer-encoding; b=jKNQliY3UX3LBdDT4GTm1jM9wZ9hD5iHFKQGRzshNGrR2gRr+PMkywEVyq/6hS13ct +P1okT3Kzti+GF9tBYMtaBtJgI2umr7ug/mEQoKkBIc+skPt3lRE2Gly4iORkXfTPQaT lwwco4t4V4vS4qe5SnX1QFu+5EDqqx8Ni1hyY= MIME-Version: 1.0 Received: by 10.204.137.68 with SMTP id v4mr3849531bkt.115.1305131924727; Wed, 11 May 2011 09:38:44 -0700 (PDT) Received: by 10.204.68.19 with HTTP; Wed, 11 May 2011 09:38:44 -0700 (PDT) In-Reply-To: References: Date: Wed, 11 May 2011 12:38:44 -0400 Message-ID: Subject: Re: Poor performance when joining against inherited tables From: Robert Haas To: Lucas Madar Cc: pgsql-performance@postgresql.org Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.583 tagged_above=-10 required=5 tests=BAYES_00=-1.9, FREEMAIL_FROM=0.001, RFC_ABUSE_POST=0.001, SARE_MILLIONSOF=0.315 X-Spam-Level: X-Archive-Number: 201105/154 X-Sequence-Number: 43663 On Mon, Apr 11, 2011 at 4:11 PM, Lucas Madar wrote: > 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 mas= ter > table that the application uses, containing a base representation and com= mon > characteristics: > > objects ( id, ... ) > item ( id, legacyid1, legacyid2 ) > =A0| - itemXX > =A0| - 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 ); > > =A0QUERY PLAN > ------------ > =A0Hash Join =A0(cost=3D457943.85..1185186.17 rows=3D8643757 width=3D506) > =A0 Hash Cond: (f.id =3D objects.id) > =A0 -> =A0Append =A0(cost=3D0.00..224458.57 rows=3D8643757 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Seq Scan on item f =A0(cost=3D0.00..26.30 rows=3D16= 30 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Seq Scan on itemXX f =A0(cost=3D0.00..1.90 rows=3D9= 0 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Seq Scan on itemYY f =A0(cost=3D0.00..7.66 rows=3D2= 66 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Seq Scan on itemZZ f =A0(cost=3D0.00..1.02 rows=3D2= width=3D20) > =A0 =A0 =A0 =A0 ... > =A0 -> =A0Hash =A0(cost=3D158447.49..158447.49 rows=3D3941949 width=3D490= ) > =A0 =A0 =A0 =A0 -> =A0Seq Scan on objects =A0(cost=3D0.00..158447.49 rows= =3D3941949 > width=3D490) > > 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=3Dfalse), I get the > following plan: > > =A0QUERY PLAN > ------------ > =A0Hash Join =A0(cost=3D10001298843.53..290002337961.71 rows=3D8643757 wi= dth=3D506) > =A0 Hash Cond: (f.id =3D objects.id) > =A0 -> =A0Append =A0(cost=3D10000000000.00..290000536334.43 rows=3D864375= 7 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Seq Scan on item f =A0(cost=3D10000000000.00..10000= 000026.30 > rows=3D1630 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Index Scan using xxx_pkey on itemXX f =A0(cost=3D0.= 00..10.60 rows=3D90 > width=3D20) > =A0 =A0 =A0 =A0 -> =A0Index Scan using yyy_pkey on itemYY f =A0(cost=3D0.= 00..25.24 > rows=3D266 width=3D20) > =A0 =A0 =A0 =A0 -> =A0Index Scan using zzz_pkey on itemZZ f =A0(cost=3D0.= 00..9.28 rows=3D2 > width=3D20) > =A0 =A0 =A0 =A0 ... > =A0 -> =A0Hash =A0(cost=3D999347.17..999347.17 rows=3D3941949 width=3D490= ) > =A0 =A0 =A0 =A0 -> =A0Index Scan using objects_pkey on objects (cost=3D0.= 00..999347.17 > rows=3D3941949 width=3D490) > > This seems like a much more sensible query plan. I don't think so. Scanning the index to extract all the rows in a table is typically going to be a lot slower than a sequential scan. A more interesting question is why you're not getting a plan like this: Nested Loop -> Seq Scan on objects -> Append -> Index Scan using xxx_pkey on itemXX -> Index Scan using yyy_pkey on itemYY -> Index Scan using zzz_pkey on itemZZ > But it seems to think doing > a sequential scan on the *empty* item table is excessively expensive in t= his > case. > > Aside from enable_seqscan=3Dfalse, is there any way I can make the query > planner not balk over doing a seqscan on an empty table? Why would you care? A sequential scan of an empty table is very fast. --=20 Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise PostgreSQL Company