<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
		>
<channel>
	<title>Comments on: Subquery Factoring</title>
	<atom:link href="http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/</link>
	<description>Just another Oracle weblog</description>
	<lastBuildDate>Wed, 22 May 2013 12:40:08 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: CJ</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46795</link>
		<dc:creator><![CDATA[CJ]]></dc:creator>
		<pubDate>Wed, 30 May 2012 15:37:41 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46795</guid>
		<description><![CDATA[Looks like I have found my answer. The NO_MERGE hint needs to be added not to the CTE, but to every query wherein the CTE referred. 

[SOURCECODE]

explain plan for
with snp as (select f_test() snap_id from dual)
select /*+ no_merge(b) */ count(*)
from dba_hist_snapshot a, snp b
where (a.snap_id= b.snap_id) 
union all
select /*+ no_merge(b) */ count(*)
from dba_hist_snapshot a, snp b
where (a.snap_id &lt; b.snap_id) ;

--------------------------------------------------------------------------------------
&#124; Id  &#124; Operation            &#124; Name          &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT     &#124;               &#124;     2 &#124;    40 &#124;   211  (51)&#124; 00:00:01 &#124;
&#124;   1 &#124;  UNION-ALL           &#124;               &#124;       &#124;       &#124;            &#124;          &#124;
&#124;   2 &#124;   SORT AGGREGATE     &#124;               &#124;     1 &#124;    20 &#124;            &#124;          &#124;
&#124;*  3 &#124;    HASH JOIN         &#124;               &#124;     4 &#124;    80 &#124;   106   (2)&#124; 00:00:01 &#124;
&#124;   4 &#124;     VIEW             &#124;               &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   5 &#124;      FAST DUAL       &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;*  6 &#124;     TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124; 16314 &#124;   111K&#124;   103   (1)&#124; 00:00:01 &#124;
&#124;   7 &#124;   SORT AGGREGATE     &#124;               &#124;     1 &#124;    20 &#124;            &#124;          &#124;
&#124;   8 &#124;    NESTED LOOPS      &#124;               &#124;   816 &#124; 16320 &#124;   105   (1)&#124; 00:00:01 &#124;
&#124;   9 &#124;     VIEW             &#124;               &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;  10 &#124;      FAST DUAL       &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;* 11 &#124;     TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124;   816 &#124;  5712 &#124;   103   (1)&#124; 00:00:01 &#124;
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access(&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   6 - filter(&quot;STATUS&quot;=0)
  11 - filter(&quot;STATUS&quot;=0 AND &quot;SNAP_ID&quot;&lt;&quot;B&quot;.&quot;SNAP_ID&quot;)

[/sourcecode]

This is contrary to my earlier perception that NO_MERGE hint had to be added to the CTE and not anywhere else. Which one is correct?

Many thanks.]]></description>
		<content:encoded><![CDATA[<p>Looks like I have found my answer. The NO_MERGE hint needs to be added not to the CTE, but to every query wherein the CTE referred. </p>
<p>[SOURCECODE]</p>
<p>explain plan for<br />
with snp as (select f_test() snap_id from dual)<br />
select /*+ no_merge(b) */ count(*)<br />
from dba_hist_snapshot a, snp b<br />
where (a.snap_id= b.snap_id)<br />
union all<br />
select /*+ no_merge(b) */ count(*)<br />
from dba_hist_snapshot a, snp b<br />
where (a.snap_id &lt; b.snap_id) ;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation            | Name          | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT     |               |     2 |    40 |   211  (51)| 00:00:01 |<br />
|   1 |  UNION-ALL           |               |       |       |            |          |<br />
|   2 |   SORT AGGREGATE     |               |     1 |    20 |            |          |<br />
|*  3 |    HASH JOIN         |               |     4 |    80 |   106   (2)| 00:00:01 |<br />
|   4 |     VIEW             |               |     1 |    13 |     2   (0)| 00:00:01 |<br />
|   5 |      FAST DUAL       |               |     1 |       |     2   (0)| 00:00:01 |<br />
|*  6 |     TABLE ACCESS FULL| WRM$_SNAPSHOT | 16314 |   111K|   103   (1)| 00:00:01 |<br />
|   7 |   SORT AGGREGATE     |               |     1 |    20 |            |          |<br />
|   8 |    NESTED LOOPS      |               |   816 | 16320 |   105   (1)| 00:00:01 |<br />
|   9 |     VIEW             |               |     1 |    13 |     2   (0)| 00:00:01 |<br />
|  10 |      FAST DUAL       |               |     1 |       |     2   (0)| 00:00:01 |<br />
|* 11 |     TABLE ACCESS FULL| WRM$_SNAPSHOT |   816 |  5712 |   103   (1)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   3 &#8211; access(&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)<br />
   6 &#8211; filter(&quot;STATUS&quot;=0)<br />
  11 &#8211; filter(&quot;STATUS&quot;=0 AND &quot;SNAP_ID&quot;&lt;&quot;B&quot;.&quot;SNAP_ID&quot;)</p>
<p>[/sourcecode]</p>
<p>This is contrary to my earlier perception that NO_MERGE hint had to be added to the CTE and not anywhere else. Which one is correct?</p>
<p>Many thanks.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: CJ</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46794</link>
		<dc:creator><![CDATA[CJ]]></dc:creator>
		<pubDate>Wed, 30 May 2012 15:08:13 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46794</guid>
		<description><![CDATA[Jonathan sir,

A rather curious behaviour with NO_MERGE and UNION. NO_MERGE works with the query appearing last in UNION ALL, but not the query appearing before.

[sourcecode]


explain plan for
with snp as (select /*+ no_merge */ f_test() snap_id from dual)
select count(*)
from dba_hist_snapshot a, snp b
where (a.snap_id= b.snap_id) 
union all
select count(*)
from dba_hist_snapshot a, snp b
where (a.snap_id &lt; b.snap_id) 
;


--------------------------------------------------------------------------------------
&#124; Id  &#124; Operation            &#124; Name          &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT     &#124;               &#124;     2 &#124;    27 &#124;   218  (53)&#124; 00:00:01 &#124;
&#124;   1 &#124;  UNION-ALL           &#124;               &#124;       &#124;       &#124;            &#124;          &#124;
&#124;   2 &#124;   SORT AGGREGATE     &#124;               &#124;     1 &#124;     7 &#124;            &#124;          &#124;
&#124;   3 &#124;    NESTED LOOPS      &#124;               &#124;     4 &#124;    28 &#124;   113   (8)&#124; 00:00:01 &#124;
&#124;   4 &#124;     FAST DUAL        &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;*  5 &#124;     TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124;     4 &#124;    28 &#124;   111   (9)&#124; 00:00:01 &#124;
&#124;   6 &#124;   SORT AGGREGATE     &#124;               &#124;     1 &#124;    20 &#124;            &#124;          &#124;
&#124;   7 &#124;    NESTED LOOPS      &#124;               &#124;   816 &#124; 16320 &#124;   105   (1)&#124; 00:00:01 &#124;
&#124;   8 &#124;     VIEW             &#124;               &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   9 &#124;      FAST DUAL       &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;* 10 &#124;     TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124;   816 &#124;  5712 &#124;   103   (1)&#124; 00:00:01 &#124;
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - filter(&quot;SNAP_ID&quot;=&quot;F_TEST&quot;() AND &quot;STATUS&quot;=0)
  10 - filter(&quot;STATUS&quot;=0 AND &quot;SNAP_ID&quot;&lt;&quot;B&quot;.&quot;SNAP_ID&quot;)

[/sourcecode]

From the filter conditions you can see that the function will execute once for every row in the first part of UNION, whereas it will execute only once for the second part. I traced using DBMS_PROFILER to confirm this. What can be the reason? (BTW, this is why I was trying to push in the MATERIALIZE hint).

Many thanks.]]></description>
		<content:encoded><![CDATA[<p>Jonathan sir,</p>
<p>A rather curious behaviour with NO_MERGE and UNION. NO_MERGE works with the query appearing last in UNION ALL, but not the query appearing before.</p>
<pre class="brush: plain; title: ; notranslate">


explain plan for
with snp as (select /*+ no_merge */ f_test() snap_id from dual)
select count(*)
from dba_hist_snapshot a, snp b
where (a.snap_id= b.snap_id) 
union all
select count(*)
from dba_hist_snapshot a, snp b
where (a.snap_id &lt; b.snap_id) 
;


--------------------------------------------------------------------------------------
| Id  | Operation            | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |               |     2 |    27 |   218  (53)| 00:00:01 |
|   1 |  UNION-ALL           |               |       |       |            |          |
|   2 |   SORT AGGREGATE     |               |     1 |     7 |            |          |
|   3 |    NESTED LOOPS      |               |     4 |    28 |   113   (8)| 00:00:01 |
|   4 |     FAST DUAL        |               |     1 |       |     2   (0)| 00:00:01 |
|*  5 |     TABLE ACCESS FULL| WRM$_SNAPSHOT |     4 |    28 |   111   (9)| 00:00:01 |
|   6 |   SORT AGGREGATE     |               |     1 |    20 |            |          |
|   7 |    NESTED LOOPS      |               |   816 | 16320 |   105   (1)| 00:00:01 |
|   8 |     VIEW             |               |     1 |    13 |     2   (0)| 00:00:01 |
|   9 |      FAST DUAL       |               |     1 |       |     2   (0)| 00:00:01 |
|* 10 |     TABLE ACCESS FULL| WRM$_SNAPSHOT |   816 |  5712 |   103   (1)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - filter(&quot;SNAP_ID&quot;=&quot;F_TEST&quot;() AND &quot;STATUS&quot;=0)
  10 - filter(&quot;STATUS&quot;=0 AND &quot;SNAP_ID&quot;&lt;&quot;B&quot;.&quot;SNAP_ID&quot;)

</pre>
<p>From the filter conditions you can see that the function will execute once for every row in the first part of UNION, whereas it will execute only once for the second part. I traced using DBMS_PROFILER to confirm this. What can be the reason? (BTW, this is why I was trying to push in the MATERIALIZE hint).</p>
<p>Many thanks.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Jonathan Lewis</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46724</link>
		<dc:creator><![CDATA[Jonathan Lewis]]></dc:creator>
		<pubDate>Mon, 28 May 2012 16:57:39 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46724</guid>
		<description><![CDATA[CJ,

I&#039;d like a preview option as well - but it&#039;s not available.

The sourcecode tags (which you correctly put in square brackets) have an open and close form. To close you need a leading /, as in  &quot;/sourcecode&quot; (but in square brackets, not quote marks).

If you look in view &lt;em&gt;&lt;strong&gt;v$sql_hints&lt;/strong&gt;&lt;/em&gt; you will find that the &lt;strong&gt;inline &lt;/strong&gt;and &lt;strong&gt;materialize &lt;/strong&gt;hints do not have an &quot;outline version&quot; which (I believe)  means you can&#039;t inject them through a stored outline, profile, or SQL Baseline. In your case it would be sufficient to inject a &lt;em&gt;&lt;strong&gt;no_merge() &lt;/strong&gt;&lt;/em&gt;hint into the subquery factoring clause (CTE). Since the query block in the clause is &lt;em&gt;&lt;strong&gt;sel$1&lt;/strong&gt;&lt;/em&gt; you need a minimum of &lt;em&gt;&lt;strong&gt;/*+ no_merge(@sel$1) */&lt;/strong&gt;&lt;/em&gt; in your outline/profile to get the plan:

[sourcecode]
-------------------------------------------------------------------------------------
&#124; Id  &#124; Operation           &#124; Name          &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
-------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT    &#124;               &#124;     1 &#124;    19 &#124;     5  (20)&#124; 00:00:01 &#124;
&#124;   1 &#124;  SORT AGGREGATE     &#124;               &#124;     1 &#124;    19 &#124;            &#124;          &#124;
&#124;*  2 &#124;   HASH JOIN         &#124;               &#124;     1 &#124;    19 &#124;     5  (20)&#124; 00:00:01 &#124;
&#124;   3 &#124;    VIEW             &#124;               &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   4 &#124;     FAST DUAL       &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;*  5 &#124;    TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124;    54 &#124;   324 &#124;     2   (0)&#124; 00:00:01 &#124;
-------------------------------------------------------------------------------------

[/sourcecode]

Technically an alternative hint would be &lt;em&gt;&lt;strong&gt;/*+ outline_leaf(@sel$1) */&lt;/strong&gt;&lt;/em&gt;, but the &lt;em&gt;&lt;strong&gt;outline_leaf()&lt;/strong&gt;&lt;/em&gt; hint is not documented, so should not be used.]]></description>
		<content:encoded><![CDATA[<p>CJ,</p>
<p>I&#8217;d like a preview option as well &#8211; but it&#8217;s not available.</p>
<p>The sourcecode tags (which you correctly put in square brackets) have an open and close form. To close you need a leading /, as in  &#8220;/sourcecode&#8221; (but in square brackets, not quote marks).</p>
<p>If you look in view <em><strong>v$sql_hints</strong></em> you will find that the <strong>inline </strong>and <strong>materialize </strong>hints do not have an &#8220;outline version&#8221; which (I believe)  means you can&#8217;t inject them through a stored outline, profile, or SQL Baseline. In your case it would be sufficient to inject a <em><strong>no_merge() </strong></em>hint into the subquery factoring clause (CTE). Since the query block in the clause is <em><strong>sel$1</strong></em> you need a minimum of <em><strong>/*+ no_merge(@sel$1) */</strong></em> in your outline/profile to get the plan:</p>
<pre class="brush: plain; title: ; notranslate">
-------------------------------------------------------------------------------------
| Id  | Operation           | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |               |     1 |    19 |     5  (20)| 00:00:01 |
|   1 |  SORT AGGREGATE     |               |     1 |    19 |            |          |
|*  2 |   HASH JOIN         |               |     1 |    19 |     5  (20)| 00:00:01 |
|   3 |    VIEW             |               |     1 |    13 |     2   (0)| 00:00:01 |
|   4 |     FAST DUAL       |               |     1 |       |     2   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS FULL| WRM$_SNAPSHOT |    54 |   324 |     2   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

</pre>
<p>Technically an alternative hint would be <em><strong>/*+ outline_leaf(@sel$1) */</strong></em>, but the <em><strong>outline_leaf()</strong></em> hint is not documented, so should not be used.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: CJ</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46723</link>
		<dc:creator><![CDATA[CJ]]></dc:creator>
		<pubDate>Mon, 28 May 2012 16:39:20 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46723</guid>
		<description><![CDATA[And maybe a facility to delete comments.. because my earlier comment is now redundant.]]></description>
		<content:encoded><![CDATA[<p>And maybe a facility to delete comments.. because my earlier comment is now redundant.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: CJ</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46721</link>
		<dc:creator><![CDATA[CJ]]></dc:creator>
		<pubDate>Mon, 28 May 2012 15:33:24 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46721</guid>
		<description><![CDATA[I see that the &#039;sourcecode&#039; tags haven&#039;t been applied. A preview functionality here would be really helpful.]]></description>
		<content:encoded><![CDATA[<p>I see that the &#8216;sourcecode&#8217; tags haven&#8217;t been applied. A preview functionality here would be really helpful.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: CJ</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46720</link>
		<dc:creator><![CDATA[CJ]]></dc:creator>
		<pubDate>Mon, 28 May 2012 15:31:26 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46720</guid>
		<description><![CDATA[Jonathan sir,

Is it possible to &#039;push&#039; the effects of materialize hint in a query plan using SQL profile?

I am trying to attach materialize hint to a query using SQL profile, but the plan generated through the SQL profile doesn&#039;t match with the one generated through direct hint. Version is 10.2.0.5 EE on RHEL.

[sourcecode]

create or replace function f_test
return number
as 
begin
  for r in (select min(snap_id) snap_id from dba_hist_snapshot)
	loop
		  return r.snap_id;
	end loop;
end;
/

explain plan for
with snp as (select f_test() snap_id from dual)
select count(*) 
from dba_hist_snapshot a, snp b
where a.snap_id= b.snap_id;

Plan hash value: 1583531653

select * from table(dbms_xplan.display);

-------------------------------------------------------------------------------------
&#124; Id  &#124; Operation           &#124; Name          &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
-------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT    &#124;               &#124;     1 &#124;     7 &#124;   113   (8)&#124; 00:00:01 &#124;
&#124;   1 &#124;  SORT AGGREGATE     &#124;               &#124;     1 &#124;     7 &#124;            &#124;          &#124;
&#124;   2 &#124;   NESTED LOOPS      &#124;               &#124;     4 &#124;    28 &#124;   113   (8)&#124; 00:00:01 &#124;
&#124;   3 &#124;    FAST DUAL        &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;*  4 &#124;    TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124;     4 &#124;    28 &#124;   111   (9)&#124; 00:00:01 &#124;
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter(&quot;SNAP_ID&quot;=&quot;F_TEST&quot;() AND &quot;STATUS&quot;=0)

[/sourcecode]

This is not efficient, because the function will execute once per very row in the wrm$_snapshot table. An easy way to prevent this is to add a materialize hint to the CTE.

[sourcecode]

explain plan for
with snp as (select /*+ materialize */ f_test() snap_id from dual)
select count(*) 
from dba_hist_snapshot a, snp b
where a.snap_id= b.snap_id;

select * from table(dbms_xplan.display);

----------------------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                  &#124; Name                        &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time  &#124;
----------------------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT           &#124;                             &#124;     1 &#124;    20 &#124;   108   (2)&#124; 00:00:01 &#124;
&#124;   1 &#124;  TEMP TABLE TRANSFORMATION &#124;                             &#124;       &#124;       &#124;            &#124;       &#124;
&#124;   2 &#124;   LOAD AS SELECT           &#124;                             &#124;       &#124;       &#124;            &#124;       &#124;
&#124;   3 &#124;    FAST DUAL               &#124;                             &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   4 &#124;   SORT AGGREGATE           &#124;                             &#124;     1 &#124;    20 &#124;            &#124;       &#124;
&#124;*  5 &#124;    HASH JOIN               &#124;                             &#124;     4 &#124;    80 &#124;   106   (2)&#124; 00:00:01 &#124;
&#124;   6 &#124;     VIEW                   &#124;                             &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   7 &#124;      TABLE ACCESS FULL     &#124; SYS_TEMP_0FD9D7979_73A6CAFD &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;*  8 &#124;     TABLE ACCESS FULL      &#124; WRM$_SNAPSHOT               &#124; 16314 &#124;   111K&#124;   103   (1)&#124; 00:00:01 &#124;
----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access(&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   8 - filter(&quot;STATUS&quot;=0)

[/sourcecode]

With materialize hint, the function will be executed only once. The problem is - I don&#039;t have access to the source code. So the only option for me is to use SQL profile.

I took the outline data resulting from the query with materialize hint, created a SQL profile. However, the plan generated by SQL profile looks different from the one generated with materialize hint. The code to generate SQL profile is too big, so giving below a &#039;shortcut&#039; by using outline data as a hint.

[sourcecode]

select * from table(dbms_xplan.display(null, null, &#039;advanced&#039;));

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      FULL(@&quot;SEL$D67CB2D2&quot; &quot;T1&quot;@&quot;SEL$D67CB2D2&quot;)
      USE_HASH(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      LEADING(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      FULL(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      NO_ACCESS(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$3&quot;)
      OUTLINE(@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$1&quot;)
      MERGE(@&quot;SEL$3&quot;)
      OUTLINE_LEAF(@&quot;SEL$335DD26A&quot;)
      OUTLINE_LEAF(@&quot;SEL$D67CB2D2&quot;)
      OUTLINE_LEAF(@&quot;SEL$1&quot;)
      ALL_ROWS
      OPT_PARAM(&#039;_gby_hash_aggregation_enabled&#039; &#039;false&#039;)
      OPT_PARAM(&#039;optimizer_dynamic_sampling&#039; 4)
      OPTIMIZER_FEATURES_ENABLE(&#039;10.2.0.5&#039;)
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */

explain plan for
with snp as (select f_test() snap_id from dual)
select
  /*+ FULL(@&quot;SEL$D67CB2D2&quot; &quot;T1&quot;@&quot;SEL$D67CB2D2&quot;)
      USE_HASH(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      LEADING(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      FULL(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      NO_ACCESS(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$3&quot;)
      OUTLINE(@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$1&quot;)
      MERGE(@&quot;SEL$3&quot;)
      OUTLINE_LEAF(@&quot;SEL$335DD26A&quot;)
      OUTLINE_LEAF(@&quot;SEL$D67CB2D2&quot;)
      OUTLINE_LEAF(@&quot;SEL$1&quot;)
      ALL_ROWS
      OPT_PARAM(&#039;_gby_hash_aggregation_enabled&#039; &#039;false&#039;)
      OPT_PARAM(&#039;optimizer_dynamic_sampling&#039; 4)
      OPTIMIZER_FEATURES_ENABLE(&#039;10.2.0.5&#039;)
      IGNORE_OPTIM_EMBEDDED_HINTS  */
count(*) 
from dba_hist_snapshot a, snp b
where a.snap_id= b.snap_id;	

select * from table(dbms_xplan.display);

------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation            &#124; Name              &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT     &#124;                   &#124;     1 &#124;    26 &#124;   106   (2)&#124; 00:00:01 &#124;
&#124;   1 &#124;  SORT AGGREGATE      &#124;                   &#124;     1 &#124;    26 &#124;            &#124;          &#124;
&#124;*  2 &#124;   HASH JOIN          &#124;                   &#124;     4 &#124;   104 &#124;   106   (2)&#124; 00:00:01 &#124;
&#124;   3 &#124;    VIEW              &#124;                   &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   4 &#124;     FAST DUAL        &#124;                   &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   5 &#124;    VIEW              &#124; DBA_HIST_SNAPSHOT &#124; 16314 &#124;   207K&#124;   103   (1)&#124; 00:00:01 &#124;
&#124;*  6 &#124;     TABLE ACCESS FULL&#124; WRM$_SNAPSHOT     &#124; 16314 &#124;   111K&#124;   103   (1)&#124; 00:00:01 &#124;
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(&quot;A&quot;.&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   6 - filter(&quot;STATUS&quot;=0)

[/sourcecode]

The plan generated by SQL profile is not much different from above:

[sourcecode]
-------------------------------
SQL_ID  8vncgw5ygpx1b, child number 1
-------------------------------------
with snp as (select f_test() snap_id from dual) select count(*) from
dba_hist_snapshot a, snp b where a.snap_id= b.snap_id

Plan hash value: 1587178679

-------------------------------------------------------------------------------------
&#124; Id  &#124; Operation           &#124; Name          &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
-------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT    &#124;               &#124;       &#124;       &#124;   106 (100)&#124;          &#124;
&#124;   1 &#124;  SORT AGGREGATE     &#124;               &#124;     1 &#124;    20 &#124;            &#124;          &#124;
&#124;*  2 &#124;   HASH JOIN         &#124;               &#124;     4 &#124;    80 &#124;   106   (2)&#124; 00:00:01 &#124;
&#124;   3 &#124;    VIEW             &#124;               &#124;     1 &#124;    13 &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;   4 &#124;     FAST DUAL       &#124;               &#124;     1 &#124;       &#124;     2   (0)&#124; 00:00:01 &#124;
&#124;*  5 &#124;    TABLE ACCESS FULL&#124; WRM$_SNAPSHOT &#124; 16314 &#124;   111K&#124;   103   (1)&#124; 00:00:01 &#124;
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   5 - filter(&quot;STATUS&quot;=0)

Note
-----
   - SQL profile &quot;Test_Prof&quot; used for this statement
[/sourcecode]


In the latter two plan, it is using a HASH JOIN instead of NL, so I believe it will execute the function only once. But why does it not create a temp table, as it does with materialize hint? Is there any way to force this?


Many thanks.]]></description>
		<content:encoded><![CDATA[<p>Jonathan sir,</p>
<p>Is it possible to &#8216;push&#8217; the effects of materialize hint in a query plan using SQL profile?</p>
<p>I am trying to attach materialize hint to a query using SQL profile, but the plan generated through the SQL profile doesn&#8217;t match with the one generated through direct hint. Version is 10.2.0.5 EE on RHEL.</p>
<pre class="brush: plain; title: ; notranslate">

create or replace function f_test
return number
as 
begin
  for r in (select min(snap_id) snap_id from dba_hist_snapshot)
	loop
		  return r.snap_id;
	end loop;
end;
/

explain plan for
with snp as (select f_test() snap_id from dual)
select count(*) 
from dba_hist_snapshot a, snp b
where a.snap_id= b.snap_id;

Plan hash value: 1583531653

select * from table(dbms_xplan.display);

-------------------------------------------------------------------------------------
| Id  | Operation           | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |               |     1 |     7 |   113   (8)| 00:00:01 |
|   1 |  SORT AGGREGATE     |               |     1 |     7 |            |          |
|   2 |   NESTED LOOPS      |               |     4 |    28 |   113   (8)| 00:00:01 |
|   3 |    FAST DUAL        |               |     1 |       |     2   (0)| 00:00:01 |
|*  4 |    TABLE ACCESS FULL| WRM$_SNAPSHOT |     4 |    28 |   111   (9)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   4 - filter(&quot;SNAP_ID&quot;=&quot;F_TEST&quot;() AND &quot;STATUS&quot;=0)

</pre>
<p>This is not efficient, because the function will execute once per very row in the wrm$_snapshot table. An easy way to prevent this is to add a materialize hint to the CTE.</p>
<pre class="brush: plain; title: ; notranslate">

explain plan for
with snp as (select /*+ materialize */ f_test() snap_id from dual)
select count(*) 
from dba_hist_snapshot a, snp b
where a.snap_id= b.snap_id;

select * from table(dbms_xplan.display);

----------------------------------------------------------------------------------------------------------
| Id  | Operation                  | Name                        | Rows  | Bytes | Cost (%CPU)| Time  |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |                             |     1 |    20 |   108   (2)| 00:00:01 |
|   1 |  TEMP TABLE TRANSFORMATION |                             |       |       |            |       |
|   2 |   LOAD AS SELECT           |                             |       |       |            |       |
|   3 |    FAST DUAL               |                             |     1 |       |     2   (0)| 00:00:01 |
|   4 |   SORT AGGREGATE           |                             |     1 |    20 |            |       |
|*  5 |    HASH JOIN               |                             |     4 |    80 |   106   (2)| 00:00:01 |
|   6 |     VIEW                   |                             |     1 |    13 |     2   (0)| 00:00:01 |
|   7 |      TABLE ACCESS FULL     | SYS_TEMP_0FD9D7979_73A6CAFD |     1 |    13 |     2   (0)| 00:00:01 |
|*  8 |     TABLE ACCESS FULL      | WRM$_SNAPSHOT               | 16314 |   111K|   103   (1)| 00:00:01 |
----------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   5 - access(&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   8 - filter(&quot;STATUS&quot;=0)

</pre>
<p>With materialize hint, the function will be executed only once. The problem is &#8211; I don&#8217;t have access to the source code. So the only option for me is to use SQL profile.</p>
<p>I took the outline data resulting from the query with materialize hint, created a SQL profile. However, the plan generated by SQL profile looks different from the one generated with materialize hint. The code to generate SQL profile is too big, so giving below a &#8216;shortcut&#8217; by using outline data as a hint.</p>
<pre class="brush: plain; title: ; notranslate">

select * from table(dbms_xplan.display(null, null, 'advanced'));

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      FULL(@&quot;SEL$D67CB2D2&quot; &quot;T1&quot;@&quot;SEL$D67CB2D2&quot;)
      USE_HASH(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      LEADING(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      FULL(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      NO_ACCESS(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$3&quot;)
      OUTLINE(@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$1&quot;)
      MERGE(@&quot;SEL$3&quot;)
      OUTLINE_LEAF(@&quot;SEL$335DD26A&quot;)
      OUTLINE_LEAF(@&quot;SEL$D67CB2D2&quot;)
      OUTLINE_LEAF(@&quot;SEL$1&quot;)
      ALL_ROWS
      OPT_PARAM('_gby_hash_aggregation_enabled' 'false')
      OPT_PARAM('optimizer_dynamic_sampling' 4)
      OPTIMIZER_FEATURES_ENABLE('10.2.0.5')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */

explain plan for
with snp as (select f_test() snap_id from dual)
select
  /*+ FULL(@&quot;SEL$D67CB2D2&quot; &quot;T1&quot;@&quot;SEL$D67CB2D2&quot;)
      USE_HASH(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      LEADING(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      FULL(@&quot;SEL$335DD26A&quot; &quot;WRM$_SNAPSHOT&quot;@&quot;SEL$3&quot;)
      NO_ACCESS(@&quot;SEL$335DD26A&quot; &quot;B&quot;@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$3&quot;)
      OUTLINE(@&quot;SEL$2&quot;)
      OUTLINE(@&quot;SEL$1&quot;)
      MERGE(@&quot;SEL$3&quot;)
      OUTLINE_LEAF(@&quot;SEL$335DD26A&quot;)
      OUTLINE_LEAF(@&quot;SEL$D67CB2D2&quot;)
      OUTLINE_LEAF(@&quot;SEL$1&quot;)
      ALL_ROWS
      OPT_PARAM('_gby_hash_aggregation_enabled' 'false')
      OPT_PARAM('optimizer_dynamic_sampling' 4)
      OPTIMIZER_FEATURES_ENABLE('10.2.0.5')
      IGNORE_OPTIM_EMBEDDED_HINTS  */
count(*) 
from dba_hist_snapshot a, snp b
where a.snap_id= b.snap_id;	

select * from table(dbms_xplan.display);

------------------------------------------------------------------------------------------
| Id  | Operation            | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |                   |     1 |    26 |   106   (2)| 00:00:01 |
|   1 |  SORT AGGREGATE      |                   |     1 |    26 |            |          |
|*  2 |   HASH JOIN          |                   |     4 |   104 |   106   (2)| 00:00:01 |
|   3 |    VIEW              |                   |     1 |    13 |     2   (0)| 00:00:01 |
|   4 |     FAST DUAL        |                   |     1 |       |     2   (0)| 00:00:01 |
|   5 |    VIEW              | DBA_HIST_SNAPSHOT | 16314 |   207K|   103   (1)| 00:00:01 |
|*  6 |     TABLE ACCESS FULL| WRM$_SNAPSHOT     | 16314 |   111K|   103   (1)| 00:00:01 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(&quot;A&quot;.&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   6 - filter(&quot;STATUS&quot;=0)

</pre>
<p>The plan generated by SQL profile is not much different from above:</p>
<pre class="brush: plain; title: ; notranslate">
-------------------------------
SQL_ID  8vncgw5ygpx1b, child number 1
-------------------------------------
with snp as (select f_test() snap_id from dual) select count(*) from
dba_hist_snapshot a, snp b where a.snap_id= b.snap_id

Plan hash value: 1587178679

-------------------------------------------------------------------------------------
| Id  | Operation           | Name          | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |               |       |       |   106 (100)|          |
|   1 |  SORT AGGREGATE     |               |     1 |    20 |            |          |
|*  2 |   HASH JOIN         |               |     4 |    80 |   106   (2)| 00:00:01 |
|   3 |    VIEW             |               |     1 |    13 |     2   (0)| 00:00:01 |
|   4 |     FAST DUAL       |               |     1 |       |     2   (0)| 00:00:01 |
|*  5 |    TABLE ACCESS FULL| WRM$_SNAPSHOT | 16314 |   111K|   103   (1)| 00:00:01 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(&quot;SNAP_ID&quot;=&quot;B&quot;.&quot;SNAP_ID&quot;)
   5 - filter(&quot;STATUS&quot;=0)

Note
-----
   - SQL profile &quot;Test_Prof&quot; used for this statement
</pre>
<p>In the latter two plan, it is using a HASH JOIN instead of NL, so I believe it will execute the function only once. But why does it not create a temp table, as it does with materialize hint? Is there any way to force this?</p>
<p>Many thanks.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Log Buffer #273, A Carnival of the Vanities for DBAs &#124; The Pythian Blog</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46619</link>
		<dc:creator><![CDATA[Log Buffer #273, A Carnival of the Vanities for DBAs &#124; The Pythian Blog]]></dc:creator>
		<pubDate>Fri, 25 May 2012 09:31:45 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46619</guid>
		<description><![CDATA[[...] Jonathan Lewis blogs about subquery factoring. [...]]]></description>
		<content:encoded><![CDATA[<p>[...] Jonathan Lewis blogs about subquery factoring. [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: lkafle</title>
		<link>http://jonathanlewis.wordpress.com/2012/05/24/subquery-factoring-7/#comment-46616</link>
		<dc:creator><![CDATA[lkafle]]></dc:creator>
		<pubDate>Fri, 25 May 2012 03:57:58 +0000</pubDate>
		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8937#comment-46616</guid>
		<description><![CDATA[Reblogged this on &lt;a href=&quot;http://lkafle.wordpress.com/2012/05/25/557/&quot; rel=&quot;nofollow&quot;&gt;lava kafle kathmandu nepal&lt;/a&gt;.]]></description>
		<content:encoded><![CDATA[<p>Reblogged this on <a href="http://lkafle.wordpress.com/2012/05/25/557/" rel="nofollow">lava kafle kathmandu nepal</a>.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
