X-Original-To: pgsql-performance-postgresql.org@localhost.postgresql.org Received: from localhost (av.hub.org [200.46.204.144]) by postgresql.org (Postfix) with ESMTP id 7412111F6ACB for ; Thu, 6 Apr 2006 05:02:27 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 82090-05 for ; Thu, 6 Apr 2006 05:02:23 -0300 (ADT) X-Greylist: delayed 01:26:37.687512 by SQLgrey- Received: from web52305.mail.yahoo.com (web52305.mail.yahoo.com [206.190.48.148]) by postgresql.org (Postfix) with SMTP id DC52A11F6AC5 for ; Thu, 6 Apr 2006 05:02:24 -0300 (ADT) Received: (qmail 37252 invoked by uid 60001); 6 Apr 2006 02:35:44 -0000 DomainKey-Signature: a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com.au; h=Message-ID:Received:Date:From:Subject:To:MIME-Version:Content-Type:Content-Transfer-Encoding; b=BzFb+d0xba9am57lPTyZH0qh8b/mcgKJWAtGy2F7+pAXuND8aUDN6lK8qWsUM9i2ksXNdX20YNMLFM8KawiGYcZrJSv1yiiS2aQDOgXFWc2XFekbkQB0sx6ECt9+t5VQVZpO0mGoTOipj7gq5cede430EU3Po7u8v9tbMTkCaf8= ; Message-ID: <20060406023544.37250.qmail@web52305.mail.yahoo.com> Received: from [202.156.6.68] by web52305.mail.yahoo.com via HTTP; Thu, 06 Apr 2006 12:35:44 EST Date: Thu, 6 Apr 2006 12:35:44 +1000 (EST) From: Brian Herlihy Subject: Query planner is using wrong index. To: pgsql-performance@postgresql.org MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, score=0.479 required=5 tests=[DNS_FROM_RFC_ABUSE=0.479] X-Spam-Score: 0.479 X-Spam-Level: X-Archive-Number: 200604/101 X-Sequence-Number: 18185 Hi, I have a problem with the choice of index made by the query planner. My table looks like this: CREATE TABLE t ( p1 varchar not null, p2 varchar not null, p3 varchar not null, i1 integer, i2 integer, i3 integer, i4 integer, i5 integer, d1 date, d2 date, d3 date, PRIMARY KEY (p1, p2, p3) ); I have also created an index on (p2, p3), as some of my lookups are on these only. All the integers and dates are data values. The table has around 9 million rows. I am using postgresl 7.4.7 I have set statistics to 1000 on the p1, p2 and p3 columns, and run vacuum full analyse. However, I still see query plans like this: db=# explain select * from t where p1 = 'something' and p2 = 'fairly_common' and p3 = 'fairly_common'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------- Index Scan using p2p3 on t (cost=0.00..6.01 rows=1 width=102) Index Cond: (((p2)::text = 'fairly_common'::text) AND ((p3)::text = 'fairly_common'::text)) Filter: ((p1)::text = 'something'::text) (3 rows) The problem appears to be this: db=# explain select * from t where p2 = 'fairly_common' and p3 = 'fairly_common'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------- Index Scan using p2p3 on t (cost=0.00..6.01 rows=1 width=102) Index Cond: (((p2)::text = 'fairly_common'::text) AND ((p3)::text = 'fairly_common'::text)) (3 rows) The query planner thinks that this will return only 1 row. In fact, these index lookups sometimes return up to 500 rows, which then must be filtered by p1. This can take 2 or 3 seconds to execute for what should be a simple primary key lookup. For VERY common values of p2 and p3, the query planner chooses the primary key, because these values are stored explicitly in the analyse results. For rare values there is no problem, because the query runs quickly. But for "fairly common" values, there is a problem. I would like the query planner to use the primary key for all of these lookups. How can I enforce this? Thanks, Brian