Received: from makus.postgresql.org (makus.postgresql.org [98.129.198.125]) by mail.postgresql.org (Postfix) with ESMTP id 858E131F0C2 for ; Sun, 13 May 2012 19:01:10 -0300 (ADT) Received: from mail-qc0-f174.google.com ([209.85.216.174]) by makus.postgresql.org with esmtp (Exim 4.72) (envelope-from ) id 1STgqj-0003qX-1x for pgsql-performance@postgresql.org; Sun, 13 May 2012 22:01:10 +0000 Received: by qcro28 with SMTP id o28so2965103qcr.19 for ; Sun, 13 May 2012 15:00:56 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=date:from:to:cc:subject:message-id:references:mime-version :content-type:content-disposition:in-reply-to:user-agent :x-gm-message-state; bh=HOKs9wbiupx3vDzMukcQRf/XDD/5rRoY7Q41q2P4KeM=; b=GQiOO1tG2eejDFKRlDGJWQg8dAeNW0qvVCWYZ29gAhZn6pCKboRWe3gt4AaARbCxwj jvcDhbTIAAUmhgjTDUds+Xk1dFpEwHB7sRkA9aU/aHLbonrbtrs6rhypPs9PTteVToVg WnYkQX72Ssjl15v2lwkkcKb/HJBeUQFVkM1KV9hm5OcbGh+WOvq21JK1hbvu9P+J/bB7 Q+z9HaUxZFRqZ8jEyVclEegqinvQ1AZFyuHnCO1z9YL6rLfaf32wB+K3WVCpuo9Ds/g7 RHLc16nmRC1RnIrAVCkxcUfKhU+bgjcBUJEiXto/4ar70is/d8dQkAeLIIGp1WoYXlh4 JQMA== Received: by 10.229.137.11 with SMTP id u11mr2822146qct.55.1336946455959; Sun, 13 May 2012 15:00:55 -0700 (PDT) Received: from tornado.leadboat.com (ip68-105-236-221.hr.hr.cox.net. [68.105.236.221]) by mx.google.com with ESMTPS id ch15sm35934640qab.18.2012.05.13.15.00.54 (version=SSLv3 cipher=OTHER); Sun, 13 May 2012 15:00:55 -0700 (PDT) Date: Sun, 13 May 2012 18:00:53 -0400 From: Noah Misch To: Clemens Eisserer Cc: pgsql-performance@postgresql.org Subject: Re: Any disadvantages of using =ANY(ARRAY()) instead of IN? Message-ID: <20120513220053.GA25848@tornado.leadboat.com> References: <20120510082039.GA27567@tornado.leadboat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.18 (2008-05-17) X-Gm-Message-State: ALoCoQlBRU9/qI2+D5s1gzoqN7EuxHYYvj4/FVyi4brlJ8weGhOTRNXz8Z2DCWj9TbY6f2YpJEbl X-Pg-Spam-Score: -2.6 (--) X-Archive-Number: 201205/89 X-Sequence-Number: 46913 On Tue, May 01, 2012 at 04:34:10PM +0200, Clemens Eisserer wrote: > select ..... from table1 ... left outer join table 15 .... WHERE > table1.id IN (select id .... join table16 ... join table20 WHERE > table20.somevalue=?) > > Starting with some amount of joins, the optimizer starts to do quite > suboptimal things like hash-joining huge tables where selctivity would > very low. > I already raised join_collapse_limit and from_collapse_limit, but > after a certain point query planning starts to become very expensive. On Sun, May 13, 2012 at 04:35:30PM +0200, Clemens Eisserer wrote: > > Since you have 15+ tables at the top level, the genetic query optimizer should > > be kicking in and delivering a plan in reasonable time, albeit with plan > > quality hazards. ??There's a danger zone when the deterministic planner is > > still in effect but {from,join}_collapse_limit have limited the scope of its > > investigation. ??If you're in that zone and have not hand-tailored your > > explicit join order, poor plans are unsurprising. ??What exact configuration > > changes are you using? > > Basically only the changes, suggested here a year ago, which made the > problem go away for less complex queries: > > geqo_threshold = 20 > from_collapse_limit = 13 > join_collapse_limit = 13 Given those settings and the query above, the planner will break the 15 top-level tables into lists of 13 and 2 tables, the 20 subquery tables into lists of 13 and 7 tables. The split points arise from order of appearance in the query text. The planner then optimizes join order within each list but not across lists. That perfectly explains your observation of "hash-joining huge tables where selctivity would very low". If it were me, I would try two things. First, set from_collapse_limit = 100, join_collapse_limit = 100, geqo_threshold = 8. This will let the planner consider all join orders for the 35 tables; it will use the genetic query optimizer to choose one. See if the plan time and resulting plan are decent. Second, set from_collapse_limit = 100, join_collapse_limit = 100, geqo = off and EXPLAIN the query. This will take forever and might exhaust all system memory. If it does complete, you'll see the standard planner's opinion of an optimal join order. You can then modify the textual join order in your query to get the same plan despite returning to a lower join_collapse_limit. Since Hibernate is generating your queries, that may prove inconvenient. It's the remaining escape hatch if the genetic query optimizer does not suffice.