Received: from maia.hub.org (maia-2.hub.org [200.46.204.251]) by mail.postgresql.org (Postfix) with ESMTP id 02063B5DBF5 for ; Wed, 26 Oct 2011 09:55:50 -0300 (ADT) Received: from mail.postgresql.org ([200.46.204.86]) by maia.hub.org (mx1.hub.org [200.46.204.251]) (amavisd-maia, port 10024) with ESMTP id 17415-02 for ; Wed, 26 Oct 2011 12:55:43 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0-rc2 Received: from ns210619.ovh.net (ns210619.ovh.net [188.165.206.83]) by mail.postgresql.org (Postfix) with ESMTP id 96B33B5DBE0 for ; Wed, 26 Oct 2011 09:55:43 -0300 (ADT) Received: from localhost (localhost.localdomain [127.0.0.1]) by ns210619.ovh.net (Postfix) with ESMTP id 6797D3D1E429; Wed, 26 Oct 2011 14:57:41 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at ns210619.ovh.net Received: from ns210619.ovh.net ([127.0.0.1]) by localhost (ns210619.ovh.net [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 5JktGXZL5ycW; Wed, 26 Oct 2011 14:57:35 +0200 (CEST) Received: from [192.168.1.4] (119.87.220.87.dynamic.jazztel.es [87.220.87.119]) by ns210619.ovh.net (Postfix) with ESMTPA id 4DC103D1E428; Wed, 26 Oct 2011 14:57:35 +0200 (CEST) Message-ID: <4EA80348.3030203@linos.es> Date: Wed, 26 Oct 2011 14:55:36 +0200 From: Linos User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20111001 Thunderbird/7.0.1 MIME-Version: 1.0 To: Merlin Moncure CC: pgsql-performance@postgresql.org Subject: Re: CTE vs Subquery References: <4EA6E252.6030002@linos.es> <24672.1319561025@sss.pgh.pa.us> <4EA6E839.6050804@linos.es> <4EA7CC40.9000200@linos.es> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Virus-Scanned: Maia Mailguard 1.0.1 X-Spam-Status: No, hits=-1.9 tagged_above=-10 required=5 tests=BAYES_00=-1.9 X-Spam-Level: X-Archive-Number: 201110/220 X-Sequence-Number: 45442 El 26/10/11 14:23, Merlin Moncure escribió: > On Wed, Oct 26, 2011 at 4:00 AM, Linos wrote: >> El 25/10/11 19:11, Merlin Moncure escribió: >>> On Tue, Oct 25, 2011 at 11:47 AM, Linos wrote: >>>> El 25/10/11 18:43, Tom Lane escribió: >>>>> Linos writes: >>>>>> i am having any problems with performance of queries that uses CTE, can the >>>>>> join on a CTE use the index of the original table? >>>>> >>>>> CTEs act as optimization fences. This is a feature, not a bug. Use >>>>> them when you want to isolate the evaluation of a subquery. >>>>> >>>>> regards, tom lane >>>>> >>>> >>>> The truth it is that complex queries seems more readable using them (maybe a >>>> personal preference no doubt). >>>> >>>> Do have other popular databases the same behavior? SQL Server or Oracle for example? >>> >>> In my experience, SQL server also materializes them -- basically CTE >>> is short hand for 'CREATE TEMP TABLE foo AS SELECT...' then joining to >>> foo. If you want join behavior, use a join (by the way IIRC SQL >>> Server is a lot more restrictive about placement of ORDER BY). >>> >>> I like CTE current behavior -- the main place I find it awkward is in >>> use of recursive queries because the CTE fence forces me to abstract >>> the recursion behind a function, not a view since pushing the view >>> qual down into the CTE is pretty horrible: >>> >>> postgres=# explain select foo.id, (with bar as (select id from foo f >>> where f.id = foo.id) select * from bar) from foo where foo.id = 11; >>> QUERY PLAN >>> ------------------------------------------------------------------------------------- >>> Index Scan using foo_idx on foo (cost=0.00..16.57 rows=1 width=4) >>> Index Cond: (id = 11) >>> SubPlan 2 >>> -> CTE Scan on bar (cost=8.28..8.30 rows=1 width=4) >>> CTE bar >>> -> Index Scan using foo_idx on foo f (cost=0.00..8.28 >>> rows=1 width=4) >>> Index Cond: (id = $0) >>> (7 rows) >>> >>> whereas for function you can inject your qual inside the CTE pretty >>> easily. this is a different problem than the one you're describing >>> though. for the most part, CTE execution fence is a very good thing, >>> since it enforces restrictions that other features can leverage, for >>> example 'data modifying with' queries (by far my all time favorite >>> postgres enhancement). >>> >>> merlin >>> >> >> ok, i get the idea, but i still don't understand what Tom says about isolate >> evaluation, apart from the performance and the readability, if i am not using >> writable CTE or recursive CTE, what it is the difference in evaluation (about >> being isolate) of a subquery vs CTE with the same text inside. >> >> I have been using this form lately: >> >> WITH inv (SELECT item_id, >> SUM(units) AS units >> FROM invoices), >> >> quo AS (SELECT item_id, >> SUM(units) AS units >> FROM quotes) >> >> SELECT items.item_id, >> CASE WHEN inv.units IS NOT NULL THEN inv.units ELSE 0 END AS >> units_invoices, >> CASE WHEN quo.units IS NOT NULL THEN quo.units ELSE 0 END AS >> units_quotes >> >> FROM items >> LEFT JOIN inv ON inv.item_id = items.item_id >> LEFT JOIN quo ON quo.item_id = items.item_id >> >> Well this is oversimplified because i use much more tables and filter based on >> dates, but you get the idea, it seems that this type of query should use >> subqueries, no? > > Think about a query like this: > with foo as > ( > select id, volatile_func() from bar > ) > select * from baz join foo using (id) join bla using(id) limit 10; > > How many times does volatile_func() get called? How many times in the > JOIN version? The answers are different... > > One of the key features of CTEs is controlling how/when query > operations occur so you can do things like control side effects and > force query plans that the server would not otherwise choose (although > this is typically an unoptimization). > > merlin Ok, i think i understand now the difference, thanks Merlin. Regards, Miguel Ángel.