Received: from localhost (maia-2.hub.org [200.46.204.187]) by postgresql.org (Postfix) with ESMTP id 84A109FB40A for ; Thu, 17 May 2007 06:12:16 -0300 (ADT) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.187]) (amavisd-maia, port 10024) with ESMTP id 72072-07 for ; Thu, 17 May 2007 06:12:08 -0300 (ADT) X-Greylist: domain auto-whitelisted by SQLgrey-1.7.5 Received: from mail01.enterprisedb.com (mail01.enterprisedb.com [63.246.7.168]) by postgresql.org (Postfix) with ESMTP id B8E989FB400 for ; Thu, 17 May 2007 06:12:11 -0300 (ADT) Thread-Index: AceYY3zVaZzRh/yvQFazsEtpyHfYCw== Received: from [192.168.23.235] ([220.225.40.2]) by mail01.enterprisedb.com with Microsoft SMTPSVC(6.0.3790.1830); Thu, 17 May 2007 05:12:25 -0400 Message-ID: <464C1CA0.1060705@enterprisedb.com> Date: Thu, 17 May 2007 14:43:04 +0530 Content-class: urn:content-classes:message X-MimeOLE: Produced By Microsoft MimeOLE V6.00.3790.2826 Importance: normal From: "Atul Deopujari" User-Agent: Thunderbird 2.0a1 (X11/20060724) MIME-Version: 1.0 To: "Tom Lane" Cc: "Neil Conway" , Subject: Re: Planning large IN lists References: <1178821226.6034.63.camel@goldbach> <19001.1178823208@sss.pgh.pa.us> In-Reply-To: <19001.1178823208@sss.pgh.pa.us> Content-Type: text/plain; format=flowed; charset="ISO-8859-1" Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 17 May 2007 09:12:26.0312 (UTC) FILETIME=[7C9BD480:01C79863] X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200705/755 X-Sequence-Number: 103357 Hi, Tom Lane wrote: > Neil Conway writes: >> When planning queries with a large IN expression in the WHERE clause, >> the planner transforms the IN list into a scalar array expression. In >> clause_selectivity(), we estimate the selectivity of the ScalarArrayExpr >> by calling scalararraysel(), which in turn estimates the selectivity of >> *each* array element in order to determine the selectivity of the array >> expression as a whole. > >> This is quite inefficient when the IN list is large. > > That's the least of the problems. We really ought to convert such cases > into an IN (VALUES(...)) type of query, since often repeated indexscans > aren't the best implementation. > I thought of giving this a shot and while I was working on it, it occurred to me that we need to decide on a threshold value of the IN list size above which such transformation should take place. For small sizes of the IN list, scalararraysel() of IN list wins over the hash join involved in IN (VALUES(...)). But for larger sizes of the IN list, IN (VALUES(...)) comes out to be a clear winner. I would like to know what does the community think should be a heuristic value of the IN list size beyond which this transformation should take place. I was thinking of a GUC variable (or a hard coded value) which defaults to say 30. This is based on numbers from the following test: postgres=# create table w (w text); CREATE TABLE postgres=# \copy w from '/usr/share/dict/words' And run the following query with different IN list sizes explain analyze select * from w where w in ('one', 'two', ...); I got the following runtimes: ------------------------------------ IN list IN (VALUES(...)) IN size ------------------------------------ 150 ~2000 ms ~5500 ms 100 ~1500 ms ~4000 ms 80 ~1400 ms ~3000 ms 50 ~1400 ms ~2500 ms 30 ~1500 ms ~1500 ms 20 ~1400 ms ~1200 ms 10 ~1400 ms ~1200 ms ------------------------------------ The IN (VALUES(...)) gives an almost steady state behavior, while the IN runtimes deteriorate with growing list size. There would obviously be different conditions on which to base this value. I seek community opinion on this. -- Atul EnterpriseDB www.enterprisedb.com