Received: from localhost (maia-2.hub.org [200.46.204.187]) by postgresql.org (Postfix) with ESMTP id 42AC59FB29D for ; Sat, 27 Jan 2007 21:56:45 -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 23108-09 for ; Sat, 27 Jan 2007 21:56:36 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey-1.7.4 Received: from sss.pgh.pa.us (sss.pgh.pa.us [66.207.139.130]) by postgresql.org (Postfix) with ESMTP id 51F549FB27A for ; Sat, 27 Jan 2007 21:56:42 -0400 (AST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss.pgh.pa.us (8.13.6/8.13.6) with ESMTP id l0S1ud1T026082; Sat, 27 Jan 2007 20:56:39 -0500 (EST) To: Ryan Holmes cc: pgsql-performance@postgresql.org Subject: Re: IN operator causes sequential scan (vs. multiple OR expressions) In-reply-to: <4F003DBB-34E7-4E9D-A8B3-27AA0CBD66C3@hyperstep.com> References: <24016.1169941986@sss.pgh.pa.us> <4F003DBB-34E7-4E9D-A8B3-27AA0CBD66C3@hyperstep.com> Comments: In-reply-to Ryan Holmes message dated "Sat, 27 Jan 2007 17:34:12 -0800" Date: Sat, 27 Jan 2007 20:56:39 -0500 Message-ID: <26081.1169949399@sss.pgh.pa.us> From: Tom Lane X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200701/390 X-Sequence-Number: 22991 Ryan Holmes writes: > So, yes, disabling seqscan does force an index scan for the IN > version. My question now is, how do I get PostgreSQL to make the > "right" decision without disabling seqscan? I pinged you before because in a trivial test case I got indexscans out of both text and varchar cases: regression=# create table foo (f1 text unique, f2 varchar(25) unique); NOTICE: CREATE TABLE / UNIQUE will create implicit index "foo_f1_key" for table "foo" NOTICE: CREATE TABLE / UNIQUE will create implicit index "foo_f2_key" for table "foo" CREATE TABLE regression=# explain select * from foo where f1 in ('foo', 'bar'); QUERY PLAN ------------------------------------------------------------------------- Bitmap Heap Scan on foo (cost=4.52..9.86 rows=2 width=61) Recheck Cond: (f1 = ANY ('{foo,bar}'::text[])) -> Bitmap Index Scan on foo_f1_key (cost=0.00..4.52 rows=2 width=0) Index Cond: (f1 = ANY ('{foo,bar}'::text[])) (4 rows) regression=# explain select * from foo where f2 in ('foo', 'bar'); QUERY PLAN ------------------------------------------------------------------------------------- Bitmap Heap Scan on foo (cost=6.59..17.27 rows=10 width=61) Recheck Cond: ((f2)::text = ANY (('{foo,bar}'::character varying[])::text[])) -> Bitmap Index Scan on foo_f2_key (cost=0.00..6.59 rows=10 width=0) Index Cond: ((f2)::text = ANY (('{foo,bar}'::character varying[])::text[])) (4 rows) But on closer inspection the second case is not doing the right thing: notice the rowcount estimate is 10, whereas it should be only 2 because of the unique index on f2. I poked into it and realized that in 8.2 scalararraysel() fails to deal with binary-compatible datatype cases, instead falling back to a not-very-bright generic estimate. I've committed a fix for 8.2.2, but in the meantime maybe you could change your varchar column to text? regards, tom lane