Received: from maia.hub.org (unknown [200.46.204.183]) by mail.postgresql.org (Postfix) with ESMTP id 6EA7D635FA8 for ; Wed, 10 Mar 2010 12:59:52 -0400 (AST) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.183]) (amavisd-maia, port 10024) with ESMTP id 61734-07 for ; Wed, 10 Mar 2010 16:59:41 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.7.6 Received: from mail-ew0-f227.google.com (mail-ew0-f227.google.com [209.85.219.227]) by mail.postgresql.org (Postfix) with ESMTP id 87868635F95 for ; Wed, 10 Mar 2010 12:59:41 -0400 (AST) Received: by ewy27 with SMTP id 27so4056597ewy.34 for ; Wed, 10 Mar 2010 08:59:40 -0800 (PST) Received: by 10.213.106.199 with SMTP id y7mr1091553ebo.55.1268240380449; Wed, 10 Mar 2010 08:59:40 -0800 (PST) Received: from [192.168.1.100] (hau59-1-87-90-41-82.dsl.club-internet.fr [87.90.41.82]) by mx.google.com with ESMTPS id 16sm4108630ewy.15.2010.03.10.08.59.39 (version=TLSv1/SSLv3 cipher=RC4-MD5); Wed, 10 Mar 2010 08:59:39 -0800 (PST) Message-ID: <4B97CFFA.6030000@nuxeo.com> Date: Wed, 10 Mar 2010 17:59:38 +0100 From: Benoit Delbosc User-Agent: Thunderbird 2.0.0.23 (X11/20090817) MIME-Version: 1.0 To: Tom Lane CC: pgsql-performance@postgresql.org Subject: Re: Bad query plan inside EXISTS clause References: <4B979DFC.7080509@nuxeo.com> <15947.1268235860@sss.pgh.pa.us> In-Reply-To: <15947.1268235860@sss.pgh.pa.us> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-2.599 tagged_above=-10 required=5 tests=BAYES_00=-2.599 X-Spam-Level: X-Archive-Number: 201003/116 X-Sequence-Number: 37941 Tom Lane a écrit : > Benoit Delbosc writes: >> I am trying to understand why inside an EXISTS clause the query planner >> does not use the index: > > I'm not sure this plan is as bad as all that. The key point is that the > planner is expecting 52517 rows that match that users_md5 value (and the > true number is evidently 51446, so that estimate isn't far off). That's > about 1/48th of the table. It knows that the EXISTS case can stop as > soon as it finds one match, so it's betting that a plain seqscan will > hit a match faster than an index lookup would be able to, ie, > seqscanning about 48 tuples is faster than one index lookup. This might > be a bad bet if the users_md5 values are correlated with physical order, > ie the matches are not randomly scattered but are all towards the end of > the table. exact, the data is not randomly scattered but ordered this explains why in my case seq scan is a bad bet Barring that, though, it could be a good bet if the table > isn't swapped in. Which is what the default cost parameters are set > up to assume. there are lots of shared buffers and effective memory on this instance, the query is executed many times I can assume that the table isn't swapped in right ? > I suspect your real complaint is that you expect the table to be swapped > in, in which case what you ought to be doing is adjusting the planner's > cost parameters. Some playing around here with a similar case suggests > that even a small reduction in random_page_cost would make it prefer an > indexscan for this type of situation. excellent ! Changing the random_page_cost from 4 to 2 do the trick SET random_page_cost = 2; EXPLAIN ANALYZE SELECT 1 WHERE EXISTS (SELECT 1 FROM read_acls_cache WHERE users_md5 = '9bc9012eb29c0bb2ae3cc7b5e78c2acf'); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------- Result (cost=1.06..1.07 rows=1 width=0) (actual time=0.048..0.048 rows=1 loops=1) One-Time Filter: $0 InitPlan 1 (returns $0) -> Index Scan using read_acls_cache_users_md5_idx on read_acls_cache (cost=0.00..55664.21 rows=52517 width=0) (actual time=0.045..0.045 rows=1 loops=1) Index Cond: ((users_md5)::text = '9bc9012eb29c0bb2ae3cc7b5e78c2acf'::text) Total runtime: 0.087 ms (6 rows) 466/0.087 = 5360 thanks ! kind regards ben