<?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: Query Executes in Seconds with the RULE Hint and Several Minutes Otherwise &#8211; What Would You Do?</title>
	<atom:link href="http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/feed/" rel="self" type="application/rss+xml" />
	<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/</link>
	<description>Miscellaneous Random Oracle Topics: Stop, Think, ... Understand</description>
	<lastBuildDate>Mon, 13 May 2013 14:10:06 +0000</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2663</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Wed, 12 Jan 2011 00:17:13 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2663</guid>
		<description><![CDATA[Chris,

Thank you for posting this example.  I had not considered the presence of a profile as the cause... and that might explain a question like this &quot;why is my query slow when I list the columns in one order, but fast when I swap the order of the first two columns.&quot;

I think that a parallel problem might be optimizing for performance when the data volumes are small (possibly with the help of hints or a profile), and then finding that as the data volumes grow (or the data changes significantly) the original optimizations actually hurt performance.  Or, as Donatello demonstrated, if the data is loaded in such a way that a lower clustering factor is achieved, the execution plan is frozen, and then as the data is later inserted into the tables in a more or less random fashion, the clustering factor no longer approximates its original value, and thus causing the original optimizations to actually hinder performance.]]></description>
		<content:encoded><![CDATA[<p>Chris,</p>
<p>Thank you for posting this example.  I had not considered the presence of a profile as the cause&#8230; and that might explain a question like this &#8220;why is my query slow when I list the columns in one order, but fast when I swap the order of the first two columns.&#8221;</p>
<p>I think that a parallel problem might be optimizing for performance when the data volumes are small (possibly with the help of hints or a profile), and then finding that as the data volumes grow (or the data changes significantly) the original optimizations actually hurt performance.  Or, as Donatello demonstrated, if the data is loaded in such a way that a lower clustering factor is achieved, the execution plan is frozen, and then as the data is later inserted into the tables in a more or less random fashion, the clustering factor no longer approximates its original value, and thus causing the original optimizations to actually hinder performance.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Chris Saxon</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2661</link>
		<dc:creator><![CDATA[Chris Saxon]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 20:52:47 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2661</guid>
		<description><![CDATA[Other hints would also &quot;break&quot; the profile as shown above, of course. I&#039;m not trying to imply that this the only way to stop the profile being used, just that adding it does cause the plan to change (in this case), and therefore is a possible reason for the differences.]]></description>
		<content:encoded><![CDATA[<p>Other hints would also &#8220;break&#8221; the profile as shown above, of course. I&#8217;m not trying to imply that this the only way to stop the profile being used, just that adding it does cause the plan to change (in this case), and therefore is a possible reason for the differences.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Martin Preiss</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2660</link>
		<dc:creator><![CDATA[Martin Preiss]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 20:10:10 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2660</guid>
		<description><![CDATA[until 10.2 there were still some rule hints in the abysses of the server: http://jonathanlewis.wordpress.com/2010/04/13/rule-rules/. If my memory serves me well I optimized some monitoring queries on v$-views by adding rule hints some years ago (in 10.2). But the only reference I could find now for this &quot;technique&quot; is http://www.dba-oracle.com/t_tuning_oracle_dictionary_sql.htm - and so this remains anecdotal evidence ...]]></description>
		<content:encoded><![CDATA[<p>until 10.2 there were still some rule hints in the abysses of the server: <a href="http://jonathanlewis.wordpress.com/2010/04/13/rule-rules/" rel="nofollow">http://jonathanlewis.wordpress.com/2010/04/13/rule-rules/</a>. If my memory serves me well I optimized some monitoring queries on v$-views by adding rule hints some years ago (in 10.2). But the only reference I could find now for this &#8220;technique&#8221; is <a href="http://www.dba-oracle.com/t_tuning_oracle_dictionary_sql.htm" rel="nofollow">http://www.dba-oracle.com/t_tuning_oracle_dictionary_sql.htm</a> &#8211; and so this remains anecdotal evidence &#8230;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Chris Saxon</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2658</link>
		<dc:creator><![CDATA[Chris Saxon]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 16:05:37 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2658</guid>
		<description><![CDATA[SQL Profiles may also cause adding a rule hint to be faster. 

If a profile was created that no longer is the optimal plan (say before an index was created), then adding the rule hint will stop the profile being used. Consider (on an 11.2.0.1 database): 

[code]
15:52:13  DBA_USER@11GR2&gt; create table t1 as select rownum r from dual connect by level &lt;= 100000;

Table created.

15:52:46  DBA_USER@11GR2&gt; select * from t1
15:52:46   2  where  r = 1;

1 row selected.

Elapsed: 00:00:00.17

Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
&#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;    26 &#124;    47   (3)&#124; 00:00:01 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T1   &#124;     2 &#124;    26 &#124;    47   (3)&#124; 00:00:01 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(&quot;R&quot;=1)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
         48  recursive calls
          0  db block gets
        227  consistent gets
        153  physical reads
          0  redo size
        328  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

15:52:46  DBA_USER@11GR2&gt;
15:52:46  DBA_USER@11GR2&gt; set autotrace off

15:52:46  DBA_USER@11GR2&gt; set autotrace off
15:52:46  DBA_USER@11GR2&gt; col sql_text format a50
15:53:16  DBA_USER@11GR2&gt; select sql_id, sql_text
15:53:16   2  from   v$sql
15:53:17   3  where  sql_text like &#039;%from t1%where  r = 1%&#039;
15:53:17   4  and    sql_text not like &#039;%not htis%&#039;
15:53:17   5  and    lower(sql_text) not like &#039;%explain%&#039;;

SQL_ID        SQL_TEXT
------------- --------------------------------------------------
d0dqg1ky8jdfp select * from t1 where  r = 1

1 row selected.

15:53:18  DBA_USER@11GR2&gt; @create_sql_profile
old: FEEDBACK ON for 1 or more rows
new: feedback OFF
old: sqlblanklines OFF
new: sqlblanklines ON
Enter value for sql_id: d0dqg1ky8jdfp
Enter value for child_no (0):
Enter value for profile_name (PROF_sqlid_planhash):
Enter value for category (DEFAULT):
Enter value for force_matching (FALSE):
old  19: sql_id = &#039;&amp;&amp;sql_id&#039;
new  19: sql_id = &#039;d0dqg1ky8jdfp&#039;
old  20: and child_number = &amp;&amp;child_no
new  20: and child_number = 0
old  27: decode(&#039;&amp;&amp;profile_name&#039;,&#039;X0X0X0X0&#039;,&#039;PROF_&amp;&amp;sql_id&#039;&#124;&#124;&#039;_&#039;&#124;&#124;plan_hash_value,&#039;&amp;&amp;profile_name&#039;)
new  27: decode(&#039;X0X0X0X0&#039;,&#039;X0X0X0X0&#039;,&#039;PROF_d0dqg1ky8jdfp&#039;&#124;&#124;&#039;_&#039;&#124;&#124;plan_hash_value,&#039;X0X0X0X0&#039;)
old  33: sql_id = &#039;&amp;&amp;sql_id&#039;
new  33: sql_id = &#039;d0dqg1ky8jdfp&#039;
old  34: and child_number = &amp;&amp;child_no;
new  34: and child_number = 0;
old  39: category =&gt; &#039;&amp;&amp;category&#039;,
new  39: category =&gt; &#039;DEFAULT&#039;,
old  41: force_match =&gt; &amp;&amp;force_matching
new  41: force_match =&gt; false
old  52:   dbms_output.put_line(&#039;ERROR: sql_id: &#039;&#124;&#124;&#039;&amp;&amp;sql_id&#039;&#124;&#124;&#039; Child: &#039;&#124;&#124;&#039;&amp;&amp;child_no&#039;&#124;&#124;&#039; not found in v$sql.&#039;);
new  52:   dbms_output.put_line(&#039;ERROR: sql_id: &#039;&#124;&#124;&#039;d0dqg1ky8jdfp&#039;&#124;&#124;&#039; Child: &#039;&#124;&#124;&#039;0&#039;&#124;&#124;&#039; not found in v$sql.&#039;);
SQL Profile PROF_d0dqg1ky8jdfp_3617692013 created.
Elapsed: 00:00:00.12
old: sqlblanklines ON
new: sqlblanklines OFF
old: feedback OFF
new: FEEDBACK ON for 1 or more rows

15:54:28  DBA_USER@11GR2&gt; create index t_i on t1(r);

Index created.

Elapsed: 00:00:00.12
15:54:34  DBA_USER@11GR2&gt;
15:54:34  DBA_USER@11GR2&gt; set autotrace trace
15:54:34  DBA_USER@11GR2&gt;
15:54:34  DBA_USER@11GR2&gt; select /*+ rule */ * from t1
15:54:34   2  where  r = 1;

1 row selected.

Elapsed: 00:00:00.06

Execution Plan
----------------------------------------------------------
Plan hash value: 4021086813

---------------------------------
&#124; Id  &#124; Operation        &#124; Name &#124;
---------------------------------
&#124;   0 &#124; SELECT STATEMENT &#124;      &#124;
&#124;*  1 &#124;  INDEX RANGE SCAN&#124; T_I  &#124;
---------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access(&quot;R&quot;=1)

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          1  physical reads
          0  redo size
        328  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
15:54:36  DBA_USER@11GR2&gt; select * from t1
15:54:54   2  where  r = 1;

1 row selected.

Elapsed: 00:00:00.03

Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124;   135 &#124;  1755 &#124;    46   (0)&#124; 00:00:01 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T1   &#124;   135 &#124;  1755 &#124;    46   (0)&#124; 00:00:01 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(&quot;R&quot;=1)

Note
-----
   - SQL profile &quot;PROF_d0dqg1ky8jdfp_3617692013&quot; used for this statement


Statistics
----------------------------------------------------------
          7  recursive calls
          0  db block gets
        164  consistent gets
          1  physical reads
          0  redo size
        328  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

[/code]

NB - this uses Kerry Osbourne&#039;s create_sql_profile.sql script to create the profile from the plan in the shared pool: &lt;a href=&quot;http://kerryosborne.oracle-guy.com/2009/04/oracle-sql-profiles/&quot; rel=&quot;nofollow&quot;&gt;http://kerryosborne.oracle-guy.com/2009/04/oracle-sql-profiles/&lt;/a&gt;]]></description>
		<content:encoded><![CDATA[<p>SQL Profiles may also cause adding a rule hint to be faster. </p>
<p>If a profile was created that no longer is the optimal plan (say before an index was created), then adding the rule hint will stop the profile being used. Consider (on an 11.2.0.1 database): </p>
<pre class="brush: plain; title: ; notranslate">
15:52:13  DBA_USER@11GR2&gt; create table t1 as select rownum r from dual connect by level &lt;= 100000;

Table created.

15:52:46  DBA_USER@11GR2&gt; select * from t1
15:52:46   2  where  r = 1;

1 row selected.

Elapsed: 00:00:00.17

Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     2 |    26 |    47   (3)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |     2 |    26 |    47   (3)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter(&quot;R&quot;=1)

Note
-----
   - dynamic sampling used for this statement (level=2)


Statistics
----------------------------------------------------------
         48  recursive calls
          0  db block gets
        227  consistent gets
        153  physical reads
          0  redo size
        328  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

15:52:46  DBA_USER@11GR2&gt;
15:52:46  DBA_USER@11GR2&gt; set autotrace off

15:52:46  DBA_USER@11GR2&gt; set autotrace off
15:52:46  DBA_USER@11GR2&gt; col sql_text format a50
15:53:16  DBA_USER@11GR2&gt; select sql_id, sql_text
15:53:16   2  from   v$sql
15:53:17   3  where  sql_text like '%from t1%where  r = 1%'
15:53:17   4  and    sql_text not like '%not htis%'
15:53:17   5  and    lower(sql_text) not like '%explain%';

SQL_ID        SQL_TEXT
------------- --------------------------------------------------
d0dqg1ky8jdfp select * from t1 where  r = 1

1 row selected.

15:53:18  DBA_USER@11GR2&gt; @create_sql_profile
old: FEEDBACK ON for 1 or more rows
new: feedback OFF
old: sqlblanklines OFF
new: sqlblanklines ON
Enter value for sql_id: d0dqg1ky8jdfp
Enter value for child_no (0):
Enter value for profile_name (PROF_sqlid_planhash):
Enter value for category (DEFAULT):
Enter value for force_matching (FALSE):
old  19: sql_id = '&amp;&amp;sql_id'
new  19: sql_id = 'd0dqg1ky8jdfp'
old  20: and child_number = &amp;&amp;child_no
new  20: and child_number = 0
old  27: decode('&amp;&amp;profile_name','X0X0X0X0','PROF_&amp;&amp;sql_id'||'_'||plan_hash_value,'&amp;&amp;profile_name')
new  27: decode('X0X0X0X0','X0X0X0X0','PROF_d0dqg1ky8jdfp'||'_'||plan_hash_value,'X0X0X0X0')
old  33: sql_id = '&amp;&amp;sql_id'
new  33: sql_id = 'd0dqg1ky8jdfp'
old  34: and child_number = &amp;&amp;child_no;
new  34: and child_number = 0;
old  39: category =&gt; '&amp;&amp;category',
new  39: category =&gt; 'DEFAULT',
old  41: force_match =&gt; &amp;&amp;force_matching
new  41: force_match =&gt; false
old  52:   dbms_output.put_line('ERROR: sql_id: '||'&amp;&amp;sql_id'||' Child: '||'&amp;&amp;child_no'||' not found in v$sql.');
new  52:   dbms_output.put_line('ERROR: sql_id: '||'d0dqg1ky8jdfp'||' Child: '||'0'||' not found in v$sql.');
SQL Profile PROF_d0dqg1ky8jdfp_3617692013 created.
Elapsed: 00:00:00.12
old: sqlblanklines ON
new: sqlblanklines OFF
old: feedback OFF
new: FEEDBACK ON for 1 or more rows

15:54:28  DBA_USER@11GR2&gt; create index t_i on t1(r);

Index created.

Elapsed: 00:00:00.12
15:54:34  DBA_USER@11GR2&gt;
15:54:34  DBA_USER@11GR2&gt; set autotrace trace
15:54:34  DBA_USER@11GR2&gt;
15:54:34  DBA_USER@11GR2&gt; select /*+ rule */ * from t1
15:54:34   2  where  r = 1;

1 row selected.

Elapsed: 00:00:00.06

Execution Plan
----------------------------------------------------------
Plan hash value: 4021086813

---------------------------------
| Id  | Operation        | Name |
---------------------------------
|   0 | SELECT STATEMENT |      |
|*  1 |  INDEX RANGE SCAN| T_I  |
---------------------------------

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

   1 - access(&quot;R&quot;=1)

Note
-----
   - rule based optimizer used (consider using cbo)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          3  consistent gets
          1  physical reads
          0  redo size
        328  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
15:54:36  DBA_USER@11GR2&gt; select * from t1
15:54:54   2  where  r = 1;

1 row selected.

Elapsed: 00:00:00.03

Execution Plan
----------------------------------------------------------
Plan hash value: 3617692013

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   135 |  1755 |    46   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T1   |   135 |  1755 |    46   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter(&quot;R&quot;=1)

Note
-----
   - SQL profile &quot;PROF_d0dqg1ky8jdfp_3617692013&quot; used for this statement


Statistics
----------------------------------------------------------
          7  recursive calls
          0  db block gets
        164  consistent gets
          1  physical reads
          0  redo size
        328  bytes sent via SQL*Net to client
        338  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

</pre>
<p>NB &#8211; this uses Kerry Osbourne&#8217;s create_sql_profile.sql script to create the profile from the plan in the shared pool: <a href="http://kerryosborne.oracle-guy.com/2009/04/oracle-sql-profiles/" rel="nofollow">http://kerryosborne.oracle-guy.com/2009/04/oracle-sql-profiles/</a></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2656</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 13:28:53 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2656</guid>
		<description><![CDATA[Martin,

1) The performance improvement caused by the addition of the RULE hint could just be an illusion, for the reason that you identified.
2) Histograms - I had not even considered histograms.  I am guessing that the optimizer did not collect histograms in this case, but the presence of histograms might very well apply to other cases.
3) It is true that the RULE based optimizer does not know what to do with a function based index, although Martin Preiss (in a comment below) found that the RULE based optimizer in Oracle Database 11.1.0.7 *will* use the function based index.  So far I have tested Oracle Database 10.2.0.2, 10.2.0.5, 11.1.0.7, 11.2.0.1, and 11.2.0.2 - only 11.1.0.7 used the function based index with the RULE based optimizer.  If I set a default parallel degree for the table the cost based (ALL_ROWS) optimizer will be used when the RULE hint is specified.
4) Another very good point.  I used a single byte characterset - while it probably would not make a difference in this test case, it might make a difference in production system performance issues.
5) Nice answer.  OK, then set the MBRC system statistic to a very low value, such as 1 or 2 (then be certain to change it back afterward).

If I re-executed the script, I might see different results.  The result with the &quot;__FAST=TRUE&quot; hint, I believe, was just a lucky coincidence.

Good idea to work with the statistics manually.  Any other ideas?]]></description>
		<content:encoded><![CDATA[<p>Martin,</p>
<p>1) The performance improvement caused by the addition of the RULE hint could just be an illusion, for the reason that you identified.<br />
2) Histograms &#8211; I had not even considered histograms.  I am guessing that the optimizer did not collect histograms in this case, but the presence of histograms might very well apply to other cases.<br />
3) It is true that the RULE based optimizer does not know what to do with a function based index, although Martin Preiss (in a comment below) found that the RULE based optimizer in Oracle Database 11.1.0.7 *will* use the function based index.  So far I have tested Oracle Database 10.2.0.2, 10.2.0.5, 11.1.0.7, 11.2.0.1, and 11.2.0.2 &#8211; only 11.1.0.7 used the function based index with the RULE based optimizer.  If I set a default parallel degree for the table the cost based (ALL_ROWS) optimizer will be used when the RULE hint is specified.<br />
4) Another very good point.  I used a single byte characterset &#8211; while it probably would not make a difference in this test case, it might make a difference in production system performance issues.<br />
5) Nice answer.  OK, then set the MBRC system statistic to a very low value, such as 1 or 2 (then be certain to change it back afterward).</p>
<p>If I re-executed the script, I might see different results.  The result with the &#8220;__FAST=TRUE&#8221; hint, I believe, was just a lucky coincidence.</p>
<p>Good idea to work with the statistics manually.  Any other ideas?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2654</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 12:27:21 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2654</guid>
		<description><![CDATA[Donatello,

That is a good idea to compare the CLUSTERING_FACTOR, which is a statistic that is not considered by the RULE based optimizer.  It could be the case that the CLUSTERING_FACTOR is just poorly calculated (due to the way the statistic is calculated, if Oracle finds that it is jumping back and forth between a small number of table blocks as the index is read, that will cause the CLUSTERING_FACTOR to increase significantly, while the actual performance impact can be quite small) - in which case a manual change to the index&#039;s calculated CLUSTERING_FACTOR statistic might help if the index was used by the RULE based optimizer and not the cost based optimizer (as might be the case when the test case is executed on 11.1.0.7, or if a normal index were used).

I tried your test case (with the ORDER BY 10 in the INSERT INTO SQL statement) on 10.2.0.2 and found that the index was not used automatically (but there is a reason for this).  Below are my results for the modified test case:
[code]
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

38462 rows selected.

Elapsed: 00:00:01.68

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124; 38462 &#124;  4995K&#124;  1040  (10)&#124; 00:00:05 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124; 38462 &#124;  4995K&#124;  1040  (10)&#124; 00:00:05 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19327  consistent gets
      19278  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
 
[code]
SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

38462 rows selected.

Elapsed: 00:00:00.98

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

----------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124;
----------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124;
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)

Note
-----
   - rule based optimizer used (consider using cbo)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19327  consistent gets
      10340  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
 
[code]
SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

38462 rows selected.

Elapsed: 00:00:00.98

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124; 38462 &#124;  4995K&#124;  1040  (10)&#124; 00:00:05 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124; 38462 &#124;  4995K&#124;  1040  (10)&#124; 00:00:05 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19327  consistent gets
      10364  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
 
[code]
SQL&gt; SELECT /*+ INDEX(T5 IND_T5_C10_F) */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

38462 rows selected.

Elapsed: 00:00:00.67

Execution Plan
----------------------------------------------------------
Plan hash value: 1769636183

--------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name         &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;              &#124; 38462 &#124;  4995K&#124;  1081   (1)&#124; 00:00:06 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5           &#124; 38462 &#124;  4995K&#124;  1081   (1)&#124; 00:00:06 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10_F &#124; 38462 &#124;       &#124;   339   (1)&#124; 00:00:02 &#124;
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)
 
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1154  consistent gets
        337  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
As you can see from the above, the calculated cost for the full table scan access path is 1040, while the calculated cost for the index access path is 1081 - so a full table scan was still used.  Why did this happen?  Let&#039;s take a look at the system (CPU) statistics:
[code]
SELECT
  PNAME,
  PVAL1
FROM
  SYS.AUX_STATS$;
 
PNAME                PVAL1
--------------- ----------
STATUS
DSTART
DSTOP
FLAGS                    1
CPUSPEEDNW      1077.92208
IOSEEKTIM               10
IOTFRSPEED            4096
SREADTIM             4.754
MREADTIM             7.432
CPUSPEED              1335
MBRC                    32
MAXTHR               18432
SLAVETHR
[/code]
Notice in the above that MBRC is set to a value of 32, let&#039;s change that to 16 to see what happens: 
[code]
EXEC DBMS_STATS.SET_SYSTEM_STATS(&#039;MBRC&#039;,16)
[/code]
Now to rerun the queries, skipping the output from the first query:
[code]
...
SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

38462 rows selected.

Elapsed: 00:00:00.81

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

----------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124;
----------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124;
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)

Note
-----
   - rule based optimizer used (consider using cbo)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      19327  consistent gets
      10349  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
So, the RULE based optimizer continues to use a full table scan, how about the cost based optimizer? 
[code]
SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

38462 rows selected.

Elapsed: 00:00:01.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1769636183

--------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name         &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;              &#124; 38462 &#124;  4995K&#124;  1081   (1)&#124; 00:00:06 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5           &#124; 38462 &#124;  4995K&#124;  1081   (1)&#124; 00:00:06 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10_F &#124; 38462 &#124;       &#124;   339   (1)&#124; 00:00:02 &#124;
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      19327  consistent gets
      10364  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
The above shows that the cost based optimizer is now using the index access path, because we modified the MBRC system (CPU) statistic.

Let&#039;s try a slight variation of the original test case, this time we will not create a function based index, I have removed the LOWER function from the WHERE clauses, and have reset the MBRC system statistic back to a value of 32 (you can optionally remove the ORDER BY 10 clause in the INSERT INTO statement):
[code]
DROP TABLE T5 PURGE;
 
CREATE TABLE T5 (
  C1 NUMBER,
  C2 NUMBER,
  C3 NUMBER,
  C4 NUMBER,
  C5 NUMBER,
  C6 NUMBER,
  C7 NUMBER,
  C8 NUMBER,
  C9 VARCHAR2(50),
  C10 VARCHAR2(50));

INSERT INTO
  T5
SELECT
  ROWNUM,
  ROWNUM,
  MOD(ROWNUM,50),
  MOD(ROWNUM,40),
  MOD(ROWNUM,100),
  ROUND(ROWNUM/1000),
  ROUND(ROWNUM/950),
  ROUND(ROWNUM/600),
  RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26))),
  RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26)))
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=1000000
ORDER BY
  10;

COMMIT;

CREATE INDEX IND_T5_C10 ON T5(C10); 

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt;USER,TABNAME=&gt;&#039;T5&#039;,CASCADE=&gt;TRUE)
 
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH BUFFER_CACHE;

SET TIMING ON
SET AUTOTRACE TRACEONLY STATISTICS EXPLAIN
SET ARRAYSIZE 1000
SET LINESIZE 140
SET TRIMSPOOL ON

SELECT 
  * 
FROM 
  T5 
WHERE 
  C10=LPAD(&#039;A&#039;,50,&#039;A&#039;); 

SELECT /*+ RULE */
  * 
FROM 
  T5 
WHERE 
  C10=LPAD(&#039;A&#039;,50,&#039;A&#039;); 

SELECT /*+ __FAST=TRUE */
  * 
FROM 
  T5 
WHERE 
  C10=LPAD(&#039;A&#039;,50,&#039;A&#039;);

SELECT /*+ INDEX(T5 IND_T5_C10) */
  * 
FROM 
  T5 
WHERE 
  C10=LPAD(&#039;A&#039;,50,&#039;A&#039;);
[/code]
 
Now let&#039;s take a look at the output:
[code]
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD(&#039;A&#039;,50,&#039;A&#039;);

38462 rows selected.

Elapsed: 00:00:01.68

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124; 38462 &#124;  4957K&#124;  1025   (8)&#124; 00:00:05 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124; 38462 &#124;  4957K&#124;  1025   (8)&#124; 00:00:05 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(&quot;C10&quot;=&#039;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#039;)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19325  consistent gets
      19278  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
As shown above, the cost based optimizer will perform a full table scan (likely because of the MBRC system statistic value).
 
[code]
SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD(&#039;A&#039;,50,&#039;A&#039;);

38462 rows selected.

Elapsed: 00:00:00.23

Execution Plan
----------------------------------------------------------
Plan hash value: 531072535

--------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name       &#124;
--------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;            &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5         &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10 &#124;
--------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(&quot;C10&quot;=&#039;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#039;)

Note
-----
   - rule based optimizer used (consider using cbo)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1152  consistent gets
        337  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
As shown above, the RULE based optimizer will use the index, because it does not care about the CLUSTERING_FACTOR of the index, nor the value of the MBRC system statistic. 

[code]
SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD(&#039;A&#039;,50,&#039;A&#039;);

38462 rows selected.

Elapsed: 00:00:00.76

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124; 38462 &#124;  4957K&#124;  1025   (8)&#124; 00:00:05 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124; 38462 &#124;  4957K&#124;  1025   (8)&#124; 00:00:05 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(&quot;C10&quot;=&#039;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#039;)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19325  consistent gets
      10449  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]
 
[code]
SQL&gt; SELECT /*+ INDEX(T5 IND_T5_C10) */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD(&#039;A&#039;,50,&#039;A&#039;);

38462 rows selected.

Elapsed: 00:00:00.23

Execution Plan
----------------------------------------------------------
Plan hash value: 531072535

------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name       &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;            &#124; 38462 &#124;  4957K&#124;  1081   (1)&#124; 00:00:06 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5         &#124; 38462 &#124;  4957K&#124;  1081   (1)&#124; 00:00:06 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10 &#124; 38462 &#124;       &#124;   339   (1)&#124; 00:00:02 &#124;
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(&quot;C10&quot;=&#039;AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA&#039;)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1152  consistent gets
          0  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]

I wonder if the comments provided by readers have now covered all of the reasons why a RULE hinted query might complete in seconds while an unhinted query might require considerably longer?]]></description>
		<content:encoded><![CDATA[<p>Donatello,</p>
<p>That is a good idea to compare the CLUSTERING_FACTOR, which is a statistic that is not considered by the RULE based optimizer.  It could be the case that the CLUSTERING_FACTOR is just poorly calculated (due to the way the statistic is calculated, if Oracle finds that it is jumping back and forth between a small number of table blocks as the index is read, that will cause the CLUSTERING_FACTOR to increase significantly, while the actual performance impact can be quite small) &#8211; in which case a manual change to the index&#8217;s calculated CLUSTERING_FACTOR statistic might help if the index was used by the RULE based optimizer and not the cost based optimizer (as might be the case when the test case is executed on 11.1.0.7, or if a normal index were used).</p>
<p>I tried your test case (with the ORDER BY 10 in the INSERT INTO SQL statement) on 10.2.0.2 and found that the index was not used automatically (but there is a reason for this).  Below are my results for the modified test case:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

38462 rows selected.

Elapsed: 00:00:01.68

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 38462 |  4995K|  1040  (10)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T5   | 38462 |  4995K|  1040  (10)| 00:00:05 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19327  consistent gets
      19278  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

38462 rows selected.

Elapsed: 00:00:00.98

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| T5   |
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')

Note
-----
   - rule based optimizer used (consider using cbo)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19327  consistent gets
      10340  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

38462 rows selected.

Elapsed: 00:00:00.98

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 38462 |  4995K|  1040  (10)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T5   | 38462 |  4995K|  1040  (10)| 00:00:05 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19327  consistent gets
      10364  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ INDEX(T5 IND_T5_C10_F) */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

38462 rows selected.

Elapsed: 00:00:00.67

Execution Plan
----------------------------------------------------------
Plan hash value: 1769636183

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              | 38462 |  4995K|  1081   (1)| 00:00:06 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5           | 38462 |  4995K|  1081   (1)| 00:00:06 |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10_F | 38462 |       |   339   (1)| 00:00:02 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
 
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1154  consistent gets
        337  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>As you can see from the above, the calculated cost for the full table scan access path is 1040, while the calculated cost for the index access path is 1081 &#8211; so a full table scan was still used.  Why did this happen?  Let&#8217;s take a look at the system (CPU) statistics:</p>
<pre class="brush: plain; title: ; notranslate">
SELECT
  PNAME,
  PVAL1
FROM
  SYS.AUX_STATS$;
 
PNAME                PVAL1
--------------- ----------
STATUS
DSTART
DSTOP
FLAGS                    1
CPUSPEEDNW      1077.92208
IOSEEKTIM               10
IOTFRSPEED            4096
SREADTIM             4.754
MREADTIM             7.432
CPUSPEED              1335
MBRC                    32
MAXTHR               18432
SLAVETHR
</pre>
<p>Notice in the above that MBRC is set to a value of 32, let&#8217;s change that to 16 to see what happens: </p>
<pre class="brush: plain; title: ; notranslate">
EXEC DBMS_STATS.SET_SYSTEM_STATS('MBRC',16)
</pre>
<p>Now to rerun the queries, skipping the output from the first query:</p>
<pre class="brush: plain; title: ; notranslate">
...
SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

38462 rows selected.

Elapsed: 00:00:00.81

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| T5   |
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')

Note
-----
   - rule based optimizer used (consider using cbo)

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      19327  consistent gets
      10349  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>So, the RULE based optimizer continues to use a full table scan, how about the cost based optimizer? </p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

38462 rows selected.

Elapsed: 00:00:01.01

Execution Plan
----------------------------------------------------------
Plan hash value: 1769636183

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              | 38462 |  4995K|  1081   (1)| 00:00:06 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5           | 38462 |  4995K|  1081   (1)| 00:00:06 |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10_F | 38462 |       |   339   (1)| 00:00:02 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')

Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      19327  consistent gets
      10364  physical reads
          0  redo size
     993542  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>The above shows that the cost based optimizer is now using the index access path, because we modified the MBRC system (CPU) statistic.</p>
<p>Let&#8217;s try a slight variation of the original test case, this time we will not create a function based index, I have removed the LOWER function from the WHERE clauses, and have reset the MBRC system statistic back to a value of 32 (you can optionally remove the ORDER BY 10 clause in the INSERT INTO statement):</p>
<pre class="brush: plain; title: ; notranslate">
DROP TABLE T5 PURGE;
 
CREATE TABLE T5 (
  C1 NUMBER,
  C2 NUMBER,
  C3 NUMBER,
  C4 NUMBER,
  C5 NUMBER,
  C6 NUMBER,
  C7 NUMBER,
  C8 NUMBER,
  C9 VARCHAR2(50),
  C10 VARCHAR2(50));

INSERT INTO
  T5
SELECT
  ROWNUM,
  ROWNUM,
  MOD(ROWNUM,50),
  MOD(ROWNUM,40),
  MOD(ROWNUM,100),
  ROUND(ROWNUM/1000),
  ROUND(ROWNUM/950),
  ROUND(ROWNUM/600),
  RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26))),
  RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26)))
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=1000000
ORDER BY
  10;

COMMIT;

CREATE INDEX IND_T5_C10 ON T5(C10); 

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt;USER,TABNAME=&gt;'T5',CASCADE=&gt;TRUE)
 
ALTER SYSTEM FLUSH BUFFER_CACHE;
ALTER SYSTEM FLUSH BUFFER_CACHE;

SET TIMING ON
SET AUTOTRACE TRACEONLY STATISTICS EXPLAIN
SET ARRAYSIZE 1000
SET LINESIZE 140
SET TRIMSPOOL ON

SELECT 
  * 
FROM 
  T5 
WHERE 
  C10=LPAD('A',50,'A'); 

SELECT /*+ RULE */
  * 
FROM 
  T5 
WHERE 
  C10=LPAD('A',50,'A'); 

SELECT /*+ __FAST=TRUE */
  * 
FROM 
  T5 
WHERE 
  C10=LPAD('A',50,'A');

SELECT /*+ INDEX(T5 IND_T5_C10) */
  * 
FROM 
  T5 
WHERE 
  C10=LPAD('A',50,'A');
</pre>
<p>Now let&#8217;s take a look at the output:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD('A',50,'A');

38462 rows selected.

Elapsed: 00:00:01.68

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 38462 |  4957K|  1025   (8)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T5   | 38462 |  4957K|  1025   (8)| 00:00:05 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(&quot;C10&quot;='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19325  consistent gets
      19278  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>As shown above, the cost based optimizer will perform a full table scan (likely because of the MBRC system statistic value).</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD('A',50,'A');

38462 rows selected.

Elapsed: 00:00:00.23

Execution Plan
----------------------------------------------------------
Plan hash value: 531072535

--------------------------------------------------
| Id  | Operation                   | Name       |
--------------------------------------------------
|   0 | SELECT STATEMENT            |            |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5         |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10 |
--------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(&quot;C10&quot;='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')

Note
-----
   - rule based optimizer used (consider using cbo)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1152  consistent gets
        337  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>As shown above, the RULE based optimizer will use the index, because it does not care about the CLUSTERING_FACTOR of the index, nor the value of the MBRC system statistic. </p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD('A',50,'A');

38462 rows selected.

Elapsed: 00:00:00.76

Execution Plan
----------------------------------------------------------
Plan hash value: 2002323537

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 38462 |  4957K|  1025   (8)| 00:00:05 |
|*  1 |  TABLE ACCESS FULL| T5   | 38462 |  4957K|  1025   (8)| 00:00:05 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter(&quot;C10&quot;='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19325  consistent gets
      10449  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT /*+ INDEX(T5 IND_T5_C10) */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    C10=LPAD('A',50,'A');

38462 rows selected.

Elapsed: 00:00:00.23

Execution Plan
----------------------------------------------------------
Plan hash value: 531072535

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            | 38462 |  4957K|  1081   (1)| 00:00:06 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5         | 38462 |  4957K|  1081   (1)| 00:00:06 |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10 | 38462 |       |   339   (1)| 00:00:02 |
------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(&quot;C10&quot;='AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')

Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       1152  consistent gets
          0  physical reads
          0  redo size
     993543  bytes sent via SQL*Net to client
        752  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>I wonder if the comments provided by readers have now covered all of the reasons why a RULE hinted query might complete in seconds while an unhinted query might require considerably longer?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Donatello Settembrino</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2652</link>
		<dc:creator><![CDATA[Donatello Settembrino]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 09:05:25 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2652</guid>
		<description><![CDATA[Hi Charles,
&quot;adjust&quot; the clustering_factor could be a solution (note the order by clause that I added in your test case in the INSERT statement).

[code]
SQL&gt; CREATE TABLE T5 (
  2    C1 NUMBER,
  3    C2 NUMBER,
  4    C3 NUMBER,
  5    C4 NUMBER,
  6    C5 NUMBER,
  7    C6 NUMBER,
  8    C7 NUMBER,
  9    C8 NUMBER,
 10    C9 VARCHAR2(50),
 11    C10 VARCHAR2(50));

Tabella creata.

Passati: 00:00:00.07
SQL&gt; INSERT INTO
  2    T5
  3  SELECT
  4    ROWNUM,
  5    ROWNUM,
  6    MOD(ROWNUM,50),
  7    MOD(ROWNUM,40),
  8    MOD(ROWNUM,100),
  9    ROUND(ROWNUM/1000),
 10    ROUND(ROWNUM/950),
 11    ROUND(ROWNUM/600),
 12    RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26))),
 13    RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26)))
 14  FROM
 15    DUAL
 16  CONNECT BY
 17    LEVEL&lt;=1000000
 18  ORDER BY 10;

SQL&gt; COMMIT;

Commit completato.

Passati: 00:00:00.04
SQL&gt; CREATE INDEX IND_T5_C10_F ON T5(LOWER(C10));

Indice creato.

Passati: 00:00:07.34
SQL&gt; EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt;USER,TABNAME=&gt;&#039;T5&#039;,CASCADE=&gt;TRUE)

Procedura PL/SQL completata correttamente.

Passati: 00:00:17.89

SQL&gt; ALTER SYSTEM FLUSH BUFFER_CACHE;

Modificato sistema.

Passati: 00:00:08.67
SQL&gt; ALTER SYSTEM FLUSH BUFFER_CACHE;

Modificato sistema.

Passati: 00:00:00.06
SQL&gt; SET AUTOTRACE TRACEONLY STATISTICS EXPLAIN
SQL&gt; SET ARRAYSIZE 1000
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

Selezionate 38462 righe.

Passati: 00:00:02.53

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 775203539

--------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name         &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;              &#124; 38462 &#124;  6911K&#124;   533   (1)&#124; 00:00:08 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5           &#124; 38462 &#124;  6911K&#124;   533   (1)&#124; 00:00:08 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10_F &#124; 38462 &#124;       &#124;   168   (1)&#124; 00:00:03 &#124;
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        608  consistent gets
        530  physical reads
          0  redo size
     987802  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed

SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

Selezionate 38462 righe.

Passati: 00:00:23.56

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 1231838660

----------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124;
----------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124;
----------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)

Note
-----
   - rule based optimizer used (consider using cbo)


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       9680  consistent gets
       9638  physical reads
          0  redo size
     987763  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed

SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

Selezionate 38462 righe.

Passati: 00:00:01.68

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 775203539

--------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name         &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;              &#124; 38462 &#124;  6911K&#124;   533   (1)&#124; 00:00:08 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5           &#124; 38462 &#124;  6911K&#124;   533   (1)&#124; 00:00:08 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10_F &#124; 38462 &#124;       &#124;   168   (1)&#124; 00:00:03 &#124;
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        608  consistent gets
          0  physical reads
          0  redo size
     987763  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed

SQL&gt; SELECT /*+ INDEX(T5 IND_T5_C10_F) */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

Selezionate 38462 righe.

Passati: 00:00:01.65

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 775203539

--------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name         &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;              &#124; 38462 &#124;  6911K&#124;   533   (1)&#124; 00:00:08 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5           &#124; 38462 &#124;  6911K&#124;   533   (1)&#124; 00:00:08 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10_F &#124; 38462 &#124;       &#124;   168   (1)&#124; 00:00:03 &#124;
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - access(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        608  consistent gets
          0  physical reads
          0  redo size
     987763  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]



Therefore, in this case the FBI is used in all cases (except the one using the hint / * + RULE * /). I can reasonably state that:

1) the execution time of the first query is reduced significantly
2) the consistent gets are reduced
3) the physical reads are reduced

Instead this is what I get from the first query if re-run your test case:

[code]
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;);

Selezionate 38462 righe.

Passati: 00:00:22.71

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 1231838660

--------------------------------------------------------------------------
&#124; Id  &#124; Operation         &#124; Name &#124; Rows  &#124; Bytes &#124; Cost (%CPU)&#124; Time     &#124;
--------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT  &#124;      &#124; 38462 &#124;  6911K&#124;  3237   (2)&#124; 00:00:46 &#124;
&#124;*  1 &#124;  TABLE ACCESS FULL&#124; T5   &#124; 38462 &#124;  6911K&#124;  3237   (2)&#124; 00:00:46 &#124;
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       9679  consistent gets
       9638  physical reads
          0  redo size
    1074775  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code]


I would say they have solved the problem, but I wonder if those who had the problem can be used
this solution.
In the real world may not be an applicable solution, depends on many factors ..
as the table is used, the queries that are executed for that table
and more...

Regards


In my test case I used the version:
[code]
SQL&gt; select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
[/code]]]></description>
		<content:encoded><![CDATA[<p>Hi Charles,<br />
&#8220;adjust&#8221; the clustering_factor could be a solution (note the order by clause that I added in your test case in the INSERT statement).</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; CREATE TABLE T5 (
  2    C1 NUMBER,
  3    C2 NUMBER,
  4    C3 NUMBER,
  5    C4 NUMBER,
  6    C5 NUMBER,
  7    C6 NUMBER,
  8    C7 NUMBER,
  9    C8 NUMBER,
 10    C9 VARCHAR2(50),
 11    C10 VARCHAR2(50));

Tabella creata.

Passati: 00:00:00.07
SQL&gt; INSERT INTO
  2    T5
  3  SELECT
  4    ROWNUM,
  5    ROWNUM,
  6    MOD(ROWNUM,50),
  7    MOD(ROWNUM,40),
  8    MOD(ROWNUM,100),
  9    ROUND(ROWNUM/1000),
 10    ROUND(ROWNUM/950),
 11    ROUND(ROWNUM/600),
 12    RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26))),
 13    RPAD(CHR(65 + MOD(ROWNUM-1,26)),50,CHR(65 + MOD(ROWNUM-1,26)))
 14  FROM
 15    DUAL
 16  CONNECT BY
 17    LEVEL&lt;=1000000
 18  ORDER BY 10;

SQL&gt; COMMIT;

Commit completato.

Passati: 00:00:00.04
SQL&gt; CREATE INDEX IND_T5_C10_F ON T5(LOWER(C10));

Indice creato.

Passati: 00:00:07.34
SQL&gt; EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt;USER,TABNAME=&gt;'T5',CASCADE=&gt;TRUE)

Procedura PL/SQL completata correttamente.

Passati: 00:00:17.89

SQL&gt; ALTER SYSTEM FLUSH BUFFER_CACHE;

Modificato sistema.

Passati: 00:00:08.67
SQL&gt; ALTER SYSTEM FLUSH BUFFER_CACHE;

Modificato sistema.

Passati: 00:00:00.06
SQL&gt; SET AUTOTRACE TRACEONLY STATISTICS EXPLAIN
SQL&gt; SET ARRAYSIZE 1000
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

Selezionate 38462 righe.

Passati: 00:00:02.53

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 775203539

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              | 38462 |  6911K|   533   (1)| 00:00:08 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5           | 38462 |  6911K|   533   (1)| 00:00:08 |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10_F | 38462 |       |   168   (1)| 00:00:03 |
--------------------------------------------------------------------------------------------

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

   2 - access(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        608  consistent gets
        530  physical reads
          0  redo size
     987802  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed

SQL&gt; SELECT /*+ RULE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

Selezionate 38462 righe.

Passati: 00:00:23.56

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 1231838660

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| T5   |
----------------------------------

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

   1 - filter(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')

Note
-----
   - rule based optimizer used (consider using cbo)


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       9680  consistent gets
       9638  physical reads
          0  redo size
     987763  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed

SQL&gt; SELECT /*+ __FAST=TRUE */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

Selezionate 38462 righe.

Passati: 00:00:01.68

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 775203539

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              | 38462 |  6911K|   533   (1)| 00:00:08 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5           | 38462 |  6911K|   533   (1)| 00:00:08 |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10_F | 38462 |       |   168   (1)| 00:00:03 |
--------------------------------------------------------------------------------------------

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

   2 - access(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        608  consistent gets
          0  physical reads
          0  redo size
     987763  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed

SQL&gt; SELECT /*+ INDEX(T5 IND_T5_C10_F) */
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

Selezionate 38462 righe.

Passati: 00:00:01.65

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 775203539

--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |              | 38462 |  6911K|   533   (1)| 00:00:08 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5           | 38462 |  6911K|   533   (1)| 00:00:08 |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10_F | 38462 |       |   168   (1)| 00:00:03 |
--------------------------------------------------------------------------------------------

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

   2 - access(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
        608  consistent gets
          0  physical reads
          0  redo size
     987763  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>Therefore, in this case the FBI is used in all cases (except the one using the hint / * + RULE * /). I can reasonably state that:</p>
<p>1) the execution time of the first query is reduced significantly<br />
2) the consistent gets are reduced<br />
3) the physical reads are reduced</p>
<p>Instead this is what I get from the first query if re-run your test case:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; SELECT
  2    *
  3  FROM
  4    T5
  5  WHERE
  6    LOWER(C10)=LPAD('a',50,'a');

Selezionate 38462 righe.

Passati: 00:00:22.71

Piano di esecuzione
----------------------------------------------------------
Plan hash value: 1231838660

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 38462 |  6911K|  3237   (2)| 00:00:46 |
|*  1 |  TABLE ACCESS FULL| T5   | 38462 |  6911K|  3237   (2)| 00:00:46 |
--------------------------------------------------------------------------

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

   1 - filter(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')


Statistiche
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       9679  consistent gets
       9638  physical reads
          0  redo size
    1074775  bytes sent via SQL*Net to client
        556  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>I would say they have solved the problem, but I wonder if those who had the problem can be used<br />
this solution.<br />
In the real world may not be an applicable solution, depends on many factors ..<br />
as the table is used, the queries that are executed for that table<br />
and more&#8230;</p>
<p>Regards</p>
<p>In my test case I used the version:</p>
<pre class="brush: plain; title: ; notranslate">
SQL&gt; select * from v$version;

BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.2.0 - 64bit Production
PL/SQL Release 11.2.0.2.0 - Production
CORE    11.2.0.2.0      Production
TNS for IBM/AIX RISC System/6000: Version 11.2.0.2.0 - Production
NLSRTL Version 11.2.0.2.0 - Production
</pre>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2649</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 03:02:24 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2649</guid>
		<description><![CDATA[Metalink (MOS) offers one more confirmation that the rule based optimizer should not have been able to use the IND_T5_C10_F function based index, as had happened in 11.1.0.7:
Doc ID 66277.1 - &quot;Concepts and Usage of Function Based Indexes&quot;
Doc ID 189702.1 - &quot;Rule Based Optimizer is to be Desupported in Oracle10g&quot; (also lists other features that are not supported by the rule based optimizer)
 
----
 
This Metalink document appears to be just what the OP of the OTN thread wanted to know:
Doc ID 247743.1 - &quot;Guidelines for Tuning: Query under Rule is fast Query under Cost is Slow&quot;]]></description>
		<content:encoded><![CDATA[<p>Metalink (MOS) offers one more confirmation that the rule based optimizer should not have been able to use the IND_T5_C10_F function based index, as had happened in 11.1.0.7:<br />
Doc ID 66277.1 &#8211; &#8220;Concepts and Usage of Function Based Indexes&#8221;<br />
Doc ID 189702.1 &#8211; &#8220;Rule Based Optimizer is to be Desupported in Oracle10g&#8221; (also lists other features that are not supported by the rule based optimizer)</p>
<p>&#8212;-</p>
<p>This Metalink document appears to be just what the OP of the OTN thread wanted to know:<br />
Doc ID 247743.1 &#8211; &#8220;Guidelines for Tuning: Query under Rule is fast Query under Cost is Slow&#8221;</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2646</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Tue, 11 Jan 2011 00:21:44 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2646</guid>
		<description><![CDATA[Martin,

Nice catch.  I can confirm that in 10.2.0.5, 11.2.0.1, and 11.2.0.2 the RULE based optimizer cannot use the IND_T5_C10_F function based index, while the RULE based optimizer in 11.1.0.7 is able to use the function based index (this happens when the RULE optimizer is hinted and also when the OPTIMIZER_MODE is set to RULE at the session level.
[code]
Elapsed: 00:00:00.26
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1769636183
 
----------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name         &#124;
----------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;              &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T5           &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T5_C10_F &#124;
----------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(LOWER(&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa&#039;)
 
Note
-----
   - rule based optimizer used (consider using cbo)
 
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19583  consistent gets
        345  physical reads
          0  redo size
    1177860  bytes sent via SQL*Net to client
        918  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
[/code] 

From a 10053 trace we see something slightly different in the predicate information section:
[code]
Considering Query Transformations on query block SEL$1 (#0)
**************************
Query transformations (QT)
**************************
CBQT bypassed for query block SEL$1 (#0): rule-based mode.
CBQT: Validity checks failed for bmqha64ws3bd9.
CSE: Considering common sub-expression elimination in query block SEL$1 (#0)
*************************
Common Subexpression elimination (CSE)
*************************
CSE:     CSE bypassed on query block SEL$1 (#0): rule-based mode.
OBYE:   Considering Order-by Elimination from view SEL$1 (#0)
***************************
Order-by elimination (OBYE)
***************************
OBYE:     OBYE bypassed: no order by to eliminate.
CVM: Considering view merge in query block SEL$1 (#0)
query block SEL$1 (#0) unchanged
Considering Query Transformations on query block SEL$1 (#0)
**************************
Query transformations (QT)
**************************
CBQT bypassed for query block SEL$1 (#0): rule-based mode.
CBQT: Validity checks failed for bmqha64ws3bd9.
CSE: Considering common sub-expression elimination in query block SEL$1 (#0)
*************************
Common Subexpression elimination (CSE)
*************************
CSE:     CSE bypassed on query block SEL$1 (#0): rule-based mode.
SU: Considering subquery unnesting in query block SEL$1 (#0)
********************
Subquery Unnest (SU)
********************
SJC: Considering set-join conversion in query block SEL$1 (#0)
*************************
Set-Join Conversion (SJC)
*************************
SJC: not performed
PM: Considering predicate move-around in query block SEL$1 (#0)
**************************
Predicate Move-Around (PM)
**************************
PM:     PM bypassed: rule-based mode.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
LOWER(&quot;T5&quot;.&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;
apadrv-start sqlid=13392027648474066345
  :
    call(in-use=1008, alloc=16344), compile(in-use=55616, alloc=61080), execution(in-use=2424, alloc=4032)
 
*******************************************
Peeked values of the binds in SQL statement
*******************************************
 
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT &quot;T5&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;T5&quot;.&quot;C2&quot; &quot;C2&quot;,&quot;T5&quot;.&quot;C3&quot; &quot;C3&quot;,&quot;T5&quot;.&quot;C4&quot; &quot;C4&quot;,&quot;T5&quot;.&quot;C5&quot; &quot;C5&quot;,&quot;T5&quot;.&quot;C6&quot; &quot;C6&quot;,&quot;T5&quot;.&quot;C7&quot; &quot;C7&quot;,&quot;T5&quot;.&quot;C8&quot; &quot;C8&quot;,&quot;T5&quot;.&quot;C9&quot; &quot;C9&quot;,&quot;T5&quot;.&quot;C10&quot; &quot;C10&quot; FROM &quot;TESTUSER&quot;.&quot;T5&quot; &quot;T5&quot; WHERE LOWER(&quot;T5&quot;.&quot;C10&quot;)=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;
apadrv-end
          :
    call(in-use=1056, alloc=16344), compile(in-use=57248, alloc=61080), execution(in-use=2504, alloc=4032)
 
Starting SQL statement dump
 
user_id=178 user_name=TESTUSER module=SQL*Plus action=
sql_id=bmqha64ws3bd9 plan_hash_value=1769636183 problem_type=0
----- Current SQL Statement for this session (sql_id=bmqha64ws3bd9) -----
SELECT /*+ RULE */
  *
FROM
  T5
WHERE
  LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;)
sql_text_length=69
sql=SELECT /*+ RULE */
  *
FROM
  T5
WHERE
  LOWER(C10)=LPAD(&#039;a&#039;,50,&#039;a&#039;)
----- Explain Plan Dump -----
----- Plan Table -----
 
============
Plan Table
============
---------------------------------------------------+-----------------------------------+
&#124; Id  &#124; Operation                    &#124; Name        &#124; Rows  &#124; Bytes &#124; Cost  &#124; Time      &#124;
---------------------------------------------------+-----------------------------------+
&#124; 0   &#124; SELECT STATEMENT             &#124;             &#124;       &#124;       &#124;       &#124;           &#124;
&#124; 1   &#124;  TABLE ACCESS BY INDEX ROWID &#124; T5          &#124;       &#124;       &#124;       &#124;           &#124;
&#124; 2   &#124;   INDEX RANGE SCAN           &#124; IND_T5_C10_F&#124;       &#124;       &#124;       &#124;           &#124;
---------------------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - access(&quot;T5&quot;.&quot;SYS_NC00011$&quot;=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)
 
Content of other_xml column
===========================
  db_version     : 11.1.0.7
  parse_schema   : TESTUSER
  plan_hash      : 1769636183
  plan_hash_2    : 3656449929
  Outline Data:
  /*+
    BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE(&#039;11.1.0.7&#039;)
      DB_VERSION(&#039;11.1.0.7&#039;)
      RBO_OUTLINE
      OUTLINE_LEAF(@&quot;SEL$1&quot;)
      INDEX_RS_ASC(@&quot;SEL$1&quot; &quot;T5&quot;@&quot;SEL$1&quot; &quot;IND_T5_C10_F&quot;)
    END_OUTLINE_DATA
  */
 
...
 
Query Block Registry:
SEL$1 0x1a4e6e40 (PARSER) [FINAL]
 
:
    call(in-use=4040, alloc=32712), compile(in-use=93032, alloc=154544), execution(in-use=11064, alloc=12144)
 
End of Optimizer State Dump
Dumping Hints
=============
  atom_hint=(@=00000002566970D8 err=0 resol=0 used=0 token=455 org=1 lvl=1 txt=RULE )
[/code]

Note in the above that the RULE based optimizer was able to use the hidden column used by the function based index:
[code]
access(&quot;T5&quot;.&quot;SYS_NC00011$&quot;=&#039;aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&#039;)
[/code]

The 10053 trace file from 11.2.0.1 showed essentially the same information as 11.1.0.7 during the hard parse.]]></description>
		<content:encoded><![CDATA[<p>Martin,</p>
<p>Nice catch.  I can confirm that in 10.2.0.5, 11.2.0.1, and 11.2.0.2 the RULE based optimizer cannot use the IND_T5_C10_F function based index, while the RULE based optimizer in 11.1.0.7 is able to use the function based index (this happens when the RULE optimizer is hinted and also when the OPTIMIZER_MODE is set to RULE at the session level.</p>
<pre class="brush: plain; title: ; notranslate">
Elapsed: 00:00:00.26
 
Execution Plan
----------------------------------------------------------
Plan hash value: 1769636183
 
----------------------------------------------------
| Id  | Operation                   | Name         |
----------------------------------------------------
|   0 | SELECT STATEMENT            |              |
|   1 |  TABLE ACCESS BY INDEX ROWID| T5           |
|*  2 |   INDEX RANGE SCAN          | IND_T5_C10_F |
----------------------------------------------------
 
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(LOWER(&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
              aaaaaa')
 
Note
-----
   - rule based optimizer used (consider using cbo)
 
Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
      19583  consistent gets
        345  physical reads
          0  redo size
    1177860  bytes sent via SQL*Net to client
        918  bytes received via SQL*Net from client
         40  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
      38462  rows processed
</pre>
<p>From a 10053 trace we see something slightly different in the predicate information section:</p>
<pre class="brush: plain; title: ; notranslate">
Considering Query Transformations on query block SEL$1 (#0)
**************************
Query transformations (QT)
**************************
CBQT bypassed for query block SEL$1 (#0): rule-based mode.
CBQT: Validity checks failed for bmqha64ws3bd9.
CSE: Considering common sub-expression elimination in query block SEL$1 (#0)
*************************
Common Subexpression elimination (CSE)
*************************
CSE:     CSE bypassed on query block SEL$1 (#0): rule-based mode.
OBYE:   Considering Order-by Elimination from view SEL$1 (#0)
***************************
Order-by elimination (OBYE)
***************************
OBYE:     OBYE bypassed: no order by to eliminate.
CVM: Considering view merge in query block SEL$1 (#0)
query block SEL$1 (#0) unchanged
Considering Query Transformations on query block SEL$1 (#0)
**************************
Query transformations (QT)
**************************
CBQT bypassed for query block SEL$1 (#0): rule-based mode.
CBQT: Validity checks failed for bmqha64ws3bd9.
CSE: Considering common sub-expression elimination in query block SEL$1 (#0)
*************************
Common Subexpression elimination (CSE)
*************************
CSE:     CSE bypassed on query block SEL$1 (#0): rule-based mode.
SU: Considering subquery unnesting in query block SEL$1 (#0)
********************
Subquery Unnest (SU)
********************
SJC: Considering set-join conversion in query block SEL$1 (#0)
*************************
Set-Join Conversion (SJC)
*************************
SJC: not performed
PM: Considering predicate move-around in query block SEL$1 (#0)
**************************
Predicate Move-Around (PM)
**************************
PM:     PM bypassed: rule-based mode.
query block SEL$1 (#0) unchanged
FPD: Considering simple filter push in query block SEL$1 (#0)
LOWER(&quot;T5&quot;.&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
apadrv-start sqlid=13392027648474066345
  :
    call(in-use=1008, alloc=16344), compile(in-use=55616, alloc=61080), execution(in-use=2424, alloc=4032)
 
*******************************************
Peeked values of the binds in SQL statement
*******************************************
 
Final query after transformations:******* UNPARSED QUERY IS *******
SELECT &quot;T5&quot;.&quot;C1&quot; &quot;C1&quot;,&quot;T5&quot;.&quot;C2&quot; &quot;C2&quot;,&quot;T5&quot;.&quot;C3&quot; &quot;C3&quot;,&quot;T5&quot;.&quot;C4&quot; &quot;C4&quot;,&quot;T5&quot;.&quot;C5&quot; &quot;C5&quot;,&quot;T5&quot;.&quot;C6&quot; &quot;C6&quot;,&quot;T5&quot;.&quot;C7&quot; &quot;C7&quot;,&quot;T5&quot;.&quot;C8&quot; &quot;C8&quot;,&quot;T5&quot;.&quot;C9&quot; &quot;C9&quot;,&quot;T5&quot;.&quot;C10&quot; &quot;C10&quot; FROM &quot;TESTUSER&quot;.&quot;T5&quot; &quot;T5&quot; WHERE LOWER(&quot;T5&quot;.&quot;C10&quot;)='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
apadrv-end
          :
    call(in-use=1056, alloc=16344), compile(in-use=57248, alloc=61080), execution(in-use=2504, alloc=4032)
 
Starting SQL statement dump
 
user_id=178 user_name=TESTUSER module=SQL*Plus action=
sql_id=bmqha64ws3bd9 plan_hash_value=1769636183 problem_type=0
----- Current SQL Statement for this session (sql_id=bmqha64ws3bd9) -----
SELECT /*+ RULE */
  *
FROM
  T5
WHERE
  LOWER(C10)=LPAD('a',50,'a')
sql_text_length=69
sql=SELECT /*+ RULE */
  *
FROM
  T5
WHERE
  LOWER(C10)=LPAD('a',50,'a')
----- Explain Plan Dump -----
----- Plan Table -----
 
============
Plan Table
============
---------------------------------------------------+-----------------------------------+
| Id  | Operation                    | Name        | Rows  | Bytes | Cost  | Time      |
---------------------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT             |             |       |       |       |           |
| 1   |  TABLE ACCESS BY INDEX ROWID | T5          |       |       |       |           |
| 2   |   INDEX RANGE SCAN           | IND_T5_C10_F|       |       |       |           |
---------------------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - access(&quot;T5&quot;.&quot;SYS_NC00011$&quot;='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
 
Content of other_xml column
===========================
  db_version     : 11.1.0.7
  parse_schema   : TESTUSER
  plan_hash      : 1769636183
  plan_hash_2    : 3656449929
  Outline Data:
  /*+
    BEGIN_OUTLINE_DATA
      IGNORE_OPTIM_EMBEDDED_HINTS
      OPTIMIZER_FEATURES_ENABLE('11.1.0.7')
      DB_VERSION('11.1.0.7')
      RBO_OUTLINE
      OUTLINE_LEAF(@&quot;SEL$1&quot;)
      INDEX_RS_ASC(@&quot;SEL$1&quot; &quot;T5&quot;@&quot;SEL$1&quot; &quot;IND_T5_C10_F&quot;)
    END_OUTLINE_DATA
  */
 
...
 
Query Block Registry:
SEL$1 0x1a4e6e40 (PARSER) [FINAL]
 
:
    call(in-use=4040, alloc=32712), compile(in-use=93032, alloc=154544), execution(in-use=11064, alloc=12144)
 
End of Optimizer State Dump
Dumping Hints
=============
  atom_hint=(@=00000002566970D8 err=0 resol=0 used=0 token=455 org=1 lvl=1 txt=RULE )
</pre>
<p>Note in the above that the RULE based optimizer was able to use the hidden column used by the function based index:</p>
<pre class="brush: plain; title: ; notranslate">
access(&quot;T5&quot;.&quot;SYS_NC00011$&quot;='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
</pre>
<p>The 10053 trace file from 11.2.0.1 showed essentially the same information as 11.1.0.7 during the hard parse.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2011/01/10/query-executes-in-seconds-with-the-rule-hint-and-several-minutes-otherwise-what-would-you-do/#comment-2643</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Mon, 10 Jan 2011 22:30:27 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=4240#comment-2643</guid>
		<description><![CDATA[Hi Kate,

You are correct that using the LOWER function on an indexed column could (or very likely will unless you do something like I did in this blog article: http://hoopercharles.wordpress.com/2010/06/01/the-instr-function-will-never-use-an-index-i-will-give-you-a-hint/ ) prevent an index on a column from being used.  

However, the statement that I used to create the index IND_T5_C10_F is this:
[code]
CREATE INDEX IND_T5_C10_F ON T5(LOWER(C10));
[/code]

The above syntax tells Oracle to create a function based index on LOWER(C10) (and store the result of that function in the index).  When defined that way, the index will only be used when LOWER(C10) appears in the WHERE clause (or in a JOIN clause in an ANSI formatted SQL statement).  

It is my understanding that the RULE based optimizer is not supposed to be able to use function based indexes.  One of the outcomes that I originally hoped would have happened is that the cost-based optimizer would have automatically selected to use the (potentially much slower) function based index access path, while the RULE based optimizer would have had to use a full table scan.  The test server, with the default value for OPTIMIZER_INDEX_COST_ADJ, and its fast random access SSD disk array, probably skewed the outcome a bit.]]></description>
		<content:encoded><![CDATA[<p>Hi Kate,</p>
<p>You are correct that using the LOWER function on an indexed column could (or very likely will unless you do something like I did in this blog article: <a href="http://hoopercharles.wordpress.com/2010/06/01/the-instr-function-will-never-use-an-index-i-will-give-you-a-hint/" rel="nofollow">http://hoopercharles.wordpress.com/2010/06/01/the-instr-function-will-never-use-an-index-i-will-give-you-a-hint/</a> ) prevent an index on a column from being used.  </p>
<p>However, the statement that I used to create the index IND_T5_C10_F is this:</p>
<pre class="brush: plain; title: ; notranslate">
CREATE INDEX IND_T5_C10_F ON T5(LOWER(C10));
</pre>
<p>The above syntax tells Oracle to create a function based index on LOWER(C10) (and store the result of that function in the index).  When defined that way, the index will only be used when LOWER(C10) appears in the WHERE clause (or in a JOIN clause in an ANSI formatted SQL statement).  </p>
<p>It is my understanding that the RULE based optimizer is not supposed to be able to use function based indexes.  One of the outcomes that I originally hoped would have happened is that the cost-based optimizer would have automatically selected to use the (potentially much slower) function based index access path, while the RULE based optimizer would have had to use a full table scan.  The test server, with the default value for OPTIMIZER_INDEX_COST_ADJ, and its fast random access SSD disk array, probably skewed the outcome a bit.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
