<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	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:slash="http://purl.org/rss/1.0/modules/slash/"
	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>Oracle Scratchpad</title>
	<atom:link href="http://jonathanlewis.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://jonathanlewis.wordpress.com</link>
	<description>Just another Oracle weblog</description>
	<lastBuildDate>Mon, 30 Jan 2012 22:25:52 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='jonathanlewis.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Oracle Scratchpad</title>
		<link>http://jonathanlewis.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://jonathanlewis.wordpress.com/osd.xml" title="Oracle Scratchpad" />
	<atom:link rel='hub' href='http://jonathanlewis.wordpress.com/?pushpress=hub'/>
		<item>
		<title>Index Hash</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/30/index-hash/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/30/index-hash/#comments</comments>
		<pubDate>Mon, 30 Jan 2012 18:12:19 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[CBO]]></category>
		<category><![CDATA[Indexing]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Troubleshooting]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8178</guid>
		<description><![CDATA[You might think from the title that this little note is going to be about the index hash join &#8211; you would be half right, it&#8217;s also about how the optimizer seems to make a complete hash of dealing with index hash joins. Let&#8217;s set up a simple data set and a couple of indexes [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8178&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>You might think from the title that this little note is going to be about the index hash join &#8211; you would be half right, it&#8217;s also about how the optimizer seems to make a complete hash of dealing with index hash joins.</p>
<p>Let&#8217;s set up a simple data set and a couple of indexes so that we can take a closer look:</p>
<p><pre class="brush: plain; gutter: false;">
create table t1
as
with generator as (
	select	--+ materialize
		rownum id
	from dual
	connect by
		level &lt;= 10000
)
select
	rownum			id,
	mod(rownum-1,20)	flag,
	lpad(rownum,10,'0')	v10,
	lpad(rownum,20,'0')	v20,
	lpad(rownum,30,'0')	v30,
	rpad('x',100)		padding
from
	generator	v1,
	generator	v2
where
	rownum &lt;= 100000
;

-- gather stats, compute, no histograms

alter table t1 add constraint t1_pk primary key(id)
	using index (create index t1_pk on t1(id))
;

create index t1_flag on t1(flag);

create index t1_ia on t1(id, v20);
create index t1_ib on t1(id, v10);
create index t1_ic on t1(id, v30);

</pre></p>
<p>The indexing is a little unusual, but does represent the sort of thing I see from time to time. In particular, the &#8220;primary key plus one more column&#8221; can be helpful to make critical queries visit only the index and not visit the table; having three such indexes is a bit over the top. Look carefully and you&#8217;ll notice that the ia, ib, ic indexes look a little out of order compared to the v20, v10, v30 columns they are built on.</p>
<p>Now try running the following SQL with autotrace enabled:</p>
<p><pre class="brush: plain; gutter: false;">
select /*+ index_ffs(t1 t1_pk) */ count(*) from t1;
select /*+ index_ffs(t1 t1_ia) */ count(*) from t1;
select /*+ index_ffs(t1 t1_ib) */ count(*) from t1;
select /*+ index_ffs(t1 t1_ic) */ count(*) from t1;
select /*+ index_ffs(t1 t1_flag) */ count(*) from t1 where flag is not null;

</pre></p>
<p>These are the results I got from 11.2.0.3 (and this test reproduces under 10.2.0.3 and 11.1.0.7). I&#8217;ve shown the full plan for the first query, but only the critical operation with its cost for the rest of them:</p>
<p><pre class="brush: plain; gutter: false;">
-------------------------------------------------------
| Id  | Operation             | Name  | Rows  | Cost  |
-------------------------------------------------------
|   0 | SELECT STATEMENT      |       |     1 |    35 |
|   1 |  SORT AGGREGATE       |       |     1 |       |
|   2 |   INDEX FAST FULL SCAN| T1_PK |   100K|    35 |
-------------------------------------------------------

|   2 |   INDEX FAST FULL SCAN| T1_IA |   100K|    80 |
|   2 |   INDEX FAST FULL SCAN| T1_IB |   100K|    59 |
|   2 |   INDEX FAST FULL SCAN| T1_IC |   100K|   101 |

|*  2 |   INDEX FAST FULL SCAN| T1_FLAG |   100K|   292K|    31 |

</pre></p>
<p>As you might expect, the longer the &#8220;extra&#8221; column, the higher the cost. It&#8217;s an interesting little detail that the queries that didn&#8217;t need to look at a data column didn&#8217;t report a &#8220;bytes&#8221; column in the execution plan &#8211; just one clue that there&#8217;s a special optimisation for the generic &#8220;count everything&#8221; query.</p>
<p>Finally, we can get to the index hash join.</p>
<p><pre class="brush: plain; gutter: false;">
select	sum(id)
from
	t1
where
	flag = 0;
;
</pre></p>
<p>Clearly, this query could do a full tablescan, but it could do a hash join between the t1_flag index and one of the other indexes. Given that the primary key index has the lowest fast full scan cost at 35, and the index fast full scan on the t1_flag index is 31, we might hope to see an index hash join with a cost of about 66. Here&#8217;s the default plan:</p>
<p><pre class="brush: plain; gutter: false;">
-----------------------------------------------------------
| Id  | Operation          | Name | Rows  | Bytes | Cost  |
-----------------------------------------------------------
|   0 | SELECT STATEMENT   |      |     1 |     8 |   380 |
|   1 |  SORT AGGREGATE    |      |     1 |     8 |       |
|*  2 |   TABLE ACCESS FULL| T1   |  5000 | 40000 |   380 |
-----------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(&quot;FLAG&quot;=0)

</pre></p>
<p>It&#8217;s a full tablescan, with a cost of 380. So let&#8217;s hint an index hash join with the two indexes we hoped to see, and find out what happens. I added the hint <strong>/*+ index_join(t1) */</strong> and got the following execution plan:</p>
<p><pre class="brush: plain; gutter: false;">
----------------------------------------------------------------------------
| Id  | Operation               | Name             | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                  |     1 |     8 |   533 |
|   1 |  SORT AGGREGATE         |                  |     1 |     8 |       |
|*  2 |   VIEW                  | index$_join$_001 |  5000 | 40000 |   533 |
|*  3 |    HASH JOIN            |                  |       |       |       |
|*  4 |     INDEX RANGE SCAN    | T1_FLAG          |  5000 | 40000 |    10 |
|   5 |     INDEX FAST FULL SCAN| T1_IA            |  5000 | 40000 |   645 |
----------------------------------------------------------------------------

</pre></p>
<p>Note three anomalies:<br />
a) Oracle has obeyed the index_join directive, but it&#8217;s used the &#8220;wrong&#8221; index<br />
b) the cost of the query (533) is less than the cost of one of its operations (645 at line 5)<br />
c) the cost of an index fast full scan on t1_ia has jumped from 80 (previous test) to 645</p>
<p>So let&#8217;s add a hint to get the right index used:</p>
<p><pre class="brush: plain; gutter: false;">
select
	/*+
		qb_name(main)
		index_join(@main t1 t1_flag t1_pk)
	*/
	sum(id)
from
	t1
where
	flag = 0
;
</pre></p>
<p>This makes no difference, Oracle still uses index t1_ia instead of t1_pk. It&#8217;s only when I include an undocumented hint that Oracle does what I want:</p>
<p><pre class="brush: plain; gutter: false;">
explain plan for
select
	/*+
		qb_name(main)
		outline_leaf(@main)
		index_join(@main t1 t1_flag t1_pk)
	*/
	sum(id)
from
	t1
where
	flag = 0
;

select * from table(dbms_xplan.display(null,null,'outline'));

----------------------------------------------------------------------------
| Id  | Operation               | Name             | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |                  |     1 |     8 |   240 |
|   1 |  SORT AGGREGATE         |                  |     1 |     8 |       |
|*  2 |   VIEW                  | index$_join$_001 |  5000 | 40000 |   240 |
|*  3 |    HASH JOIN            |                  |       |       |       |
|*  4 |     INDEX RANGE SCAN    | T1_FLAG          |  5000 | 40000 |    10 |
|   5 |     INDEX FAST FULL SCAN| T1_PK            |  5000 | 40000 |   279 |
----------------------------------------------------------------------------

Outline Data
-------------
  /*+
      BEGIN_OUTLINE_DATA
      INDEX_JOIN(@&quot;MAIN&quot; &quot;T1&quot;@&quot;MAIN&quot; (&quot;T1&quot;.&quot;FLAG&quot;) (&quot;T1&quot;.&quot;ID&quot;))
      OUTLINE(@&quot;MAIN&quot;)
      OUTLINE_LEAF(@&quot;MAIN&quot;)
      OUTLINE_LEAF(@&quot;SEL$998059AF&quot;)
      ALL_ROWS
      OPT_PARAM('_optimizer_cost_model' 'io')
      DB_VERSION('11.2.0.3')
      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(&quot;FLAG&quot;=0)
   3 - access(ROWID=ROWID)
   4 - access(&quot;FLAG&quot;=0)

</pre></p>
<p>You might note that with the right index in play<br />
a) The cost of the plan is now lower than the cost of the tablescan<br />
b) The total cost of the plan is still lower than the cost of the fast full scan<br />
c) The cost of the fast full scan in the hash join is much higher than the cost of a standalone fast full scan</p>
<h2>Analysis</h2>
<p>I&#8217;ve said many times that I hardly ever look at a 10053 trace. The trouble is, when I do have to look at a 10053 I usually want to tell everyone how clever I&#8217;ve been; this means that I can give people the impression that the only way to solve optimizer problems is to look at 10053 traces &#8211; it&#8217;s not, but this time around it seemed like a good idea.</p>
<p>Problem 1: in the calculation for the cost of the fast full scan for an index hash join, the optimizer starts by calculating the cost of an index <strong>full scan</strong>, then adds the original cost of the <strong>fast full scan</strong> to that figure.</p>
<p>Problem 2: when considering the index hash join, the optimizer looks at the indexes in alphabetical order of name, and selects the legal candidate. This is why my tests had 3 extra candidates with three different sizes. Try dropping index t1_ia and Oracle will use t1_ib; alernatively change the name of t1_ia to t1_id and, again, Oracle will use t1_ib. The primary key didn&#8217;t have a chance, being way down the alphabet at t1_pk. (In passing, I also tried re-arranging column orders &#8211; with the same results, the anomaly is not dependent on the index starting with the important column(s)).</p>
<p>Problem 3: why is the whole smaller than the sum of its parts ? Why worry about the little detail when the big picture is smashed ?</p>
<h2>Conclusion</h2>
<p>As I pointed out, I&#8217;ve run these tests on 10.2.0.3, 11.1.0.7 and 11.2.0.3 &#8211; the index hash join arithmetic is wrong. This means the optimizer may be missing opportunities where the index hash join is a good execution path. Keep an eye open for this, you may want to hint some of your SQL (and then switch the hints into SQL Baselines, if you&#8217;re running 11g). The trouble is, if you&#8217;ve got multiple candidate indexes you may sometimes have to choose between renaming indexes (to get the right one chosen &#8220;by accident&#8221;) or using an undocumented hint (and in more complex queries you&#8217;ll have to look at the outline to find out which query blocks the hint should reference).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8178/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8178/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8178/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8178&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/30/index-hash/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>Purrpetual Motion</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/27/purrpetual-motion/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/27/purrpetual-motion/#comments</comments>
		<pubDate>Fri, 27 Jan 2012 19:19:12 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[humour]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8149</guid>
		<description><![CDATA[This is a really old idea &#8211; but it&#8217;s the first time I&#8217;ve seen it illustrated. (The obvious flaw in the concept appears  in comment 22.)<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8149&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>This is a <em><strong><a href="http://whyevolutionistrue.wordpress.com/2012/01/19/perpetual-motion-machine/">really old idea</a></strong></em> &#8211; but it&#8217;s the first time I&#8217;ve seen it illustrated.</p>
<p>(The obvious flaw in the concept appears  in comment 22.)</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8149/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8149/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8149/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8149&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/27/purrpetual-motion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>Ouch!</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/26/ouch/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/26/ouch/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 20:19:43 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Troubleshooting]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8169</guid>
		<description><![CDATA[Here&#8217;s a set of Instance Activity stats I&#8217;ve never seen before, and I&#8217;d rather never see again. From an active standby running 11.1.0.7 on AIX: The instance has been up for about 60 hours &#8211; and 95% of the work it has done has been trying to find the commit times for transactions affecting blocks [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8169&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a set of Instance Activity stats I&#8217;ve never seen before, and I&#8217;d rather never see again. From an active standby running 11.1.0.7 on AIX:</p>
<p><pre class="brush: plain; gutter: false;">
select
        name, value
from    v$sysstat
where
        name in (
                'consistent gets - examination',
                'consistent gets',
                'session logical reads'
        )
or      name like 'transaction tables%'
;

NAME                                                                            VALUE
---------------------------------------------------------------- --------------------
session logical reads                                                 102,731,023,313
consistent gets                                                       102,716,499,376
consistent gets - examination                                          98,170,595,252
transaction tables consistent reads - undo records applied             96,590,314,116
transaction tables consistent read rollbacks                                2,621,019

5 rows selected.

</pre></p>
<p>The instance has been up for about 60 hours &#8211; and 95% of the work it has done has been trying to find the commit times for transactions affecting blocks that are in need of cleanout. If you look at the two statistics about the transaction tables (those are the things in the undo segment header blocks) you can see that the average work done to find a commit time was a massive 48,000 visits to undo blocks.</p>
<p>The solution was fairly simple &#8211; kill all the reports which had been running for the last six hours, because they were the ones that were causing a problem, while simultaneously suffering most from the problem &#8211; at the time I killed the worst offender it was managing to read about 50 blocks per minute from the database, and doing about 100,000 buffer visits to undo blocks per second.</p>
<p>You probably won&#8217;t see this every again, but if you do, a quick check is:<br />
<pre class="brush: plain; gutter: false;">
select * from v$sess_io order by consistent_changes; 
</pre><br />
Repeat a couple of times and check if any sessions are doing a <strong>very</strong> large number (viz: tens of thousands) of consistent changes per second.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8169/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8169/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8169/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8169&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/26/ouch/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>Quiz Night</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/19/quiz-night-16/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/19/quiz-night-16/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 08:51:53 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[Indexing]]></category>
		<category><![CDATA[Infrastructure]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8145</guid>
		<description><![CDATA[In my previous post, I made the comment: In general, if you have a three-column index that starts with the same columns in the same order as the two-column index then the three-column index will be bigger and have a higher clustering_factor. So what scenarios can you come up with that fall outside the general [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8145&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>In my <em><strong><a href="http://jonathanlewis.wordpress.com/2012/01/13/quiz-night-15/">previous post</a></strong></em>, I made the comment:</p>
<blockquote><p>
In general, if you have a three-column index that starts with the same columns in the same order as the two-column index then the three-column index will be bigger and have a higher <em><strong>clustering_factor</strong></em>.
</p></blockquote>
<p>So what scenarios can you come up with that fall outside the general case ?<br />
Alternatively, what argument could you put forward that justifies the general claim ?</p>
<p>I&#8217;ll try to respond to comments on this post a little more quickly than the last one, but I still have quite a lot of other comments to catch up on.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8145/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8145/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8145/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8145&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/19/quiz-night-16/feed/</wfw:commentRss>
		<slash:comments>23</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>Quiz Night</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/13/quiz-night-15/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/13/quiz-night-15/#comments</comments>
		<pubDate>Fri, 13 Jan 2012 18:41:30 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[Hints]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Indexing]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8101</guid>
		<description><![CDATA[Browsing a little history recently I came across a note I&#8217;d written about the new-style index hint. In that note I claimed that: &#8230; the index has to start with the columns (product_group, id) in that order – with preference given to an exact match, otherwise using the lowest cost index that starts the right [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8101&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Browsing a little history recently I came across a note I&#8217;d written about the <em><strong><a href="http://jonathanlewis.wordpress.com/2011/11/24/index-hints/">new-style index hint</a></strong></em>. In that note I claimed that:</p>
<blockquote><p><em><br />
&#8230; the index has to start with the columns (product_group, id) in that order – with preference given to an exact match, otherwise using the lowest cost index that starts the right way.<br />
</em></p></blockquote>
<p>On reading this statement I suddenly realised that I hadn&#8217;t actually proved (to myself, even) that if I had the indexes <em>(product_group, id)</em> and<em> (product_group, id, other_col)</em> then a two-column hint forced Oracle to use the two column index in all (legal) circumstances.</p>
<p>So, tonight&#8217;s quiz &#8211; are there any edge cases, and what easy ways can you think of to prove (or disprove) the claim for the general case.</p>
<p><strong>Footnote:</strong> you don&#8217;t have to demonstrate the method, just a brief outline of the idea will be sufficient.</p>
<h3>Update Jan 19th</h3>
<p>I&#8217;m sorry it&#8217;s taken so long to respond to this. It was a post that I pre-dated at the end of December, and I forgot that it would launch itself.</p>
<p>The most interesting comment, from my perspective, came from Valentin Nikotin &#8211; <em>&#8220;what if the index you are hinting is in another schema?&#8221;</em> Virtually every test I do is based on a single schema, I rarely use two, or more, schemas at the same time. So what if there&#8217;s a special case that somehow the hint has a precedence that assumes the indexes will be found by (in effect) querying <em>user_ind_columns</em> rather than <em>all_ind_columns</em> ? I wouldn&#8217;t expect this to be the case &#8211; but when you&#8217;re trying to do pre-emptive trouble-shooting it&#8217;s this type of case (i.e. &#8220;nobody does that sort of thing&#8221;) that you can easily overlook.</p>
<p>The other responents came up with the type of thing that I would call the correct strategy. We need to start with an SQL statement that uses the three-column index by default and uses the two-column index only when it&#8217;s hinted. Of course, if we can examine the 10053 trace and see the change, especially the restriction to the two-column index explicitly being labelled with something like &#8220;index demanded by user hint&#8221;, then we can be pretty confident that the interpretation is correct.</p>
<p>The question then is, how can we construct a suitable demonstration.</p>
<p>In general, if you have a three-column index that starts with the same columns in the same order as the two-column index then the three-column index will be bigger and have a higher <em><strong>clustering_factor</strong></em> so, from a purely arithmetic perspective, it will be less desirable than the two column index except for one special class of queries. Consider a query of the form:</p>
<p><pre class="brush: plain;">
select  col3
from    t1
where   col1 = {constant}
and     col2 = {constant}
</pre></p>
<p>With a suitable three-column index this query can be answered from completely within the index, with only the first two columns Oracle has to visit the table. So if we ensure that there are several rows scattered around the table we can be confident (in the general case) that the optimizer will see that the three-column query has a lower cost than the two-column query.</p>
<p>I don&#8217;t need to set up the model for you &#8211; Charles Hooper has already done the work.</p>
<p><strong>Footnote 2: </strong><br />
Following Valentin Nikotin&#8217;s comment, you might like to consider that any reports you currently run against the <em><strong>user_indexes</strong></em> and <em><strong>user_ind_columns</strong></em> views (and their partition-related equivalents) should be run against the <em><strong>all_indexes</strong></em> and <em><strong>all_ind_columns</strong></em> views with a restriction of the form: <em>&#8220;table_owner = user&#8221;</em>.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8101/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8101/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8101/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8101&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/13/quiz-night-15/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>ASH</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/11/ash/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/11/ash/#comments</comments>
		<pubDate>Wed, 11 Jan 2012 20:06:52 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8126</guid>
		<description><![CDATA[You may have noticed that I&#8217;m having a little trouble keeping up to date on the blog at the moment &#8211; I know I&#8217;ve got several comments on Oracle Core to respond to but haven&#8217;t had time to look at them yet. Very briefly, though, I thought I&#8217;d point to a note that Doug Burns [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8126&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>You may have noticed that I&#8217;m having a little trouble keeping up to date on the blog at the moment &#8211; I know I&#8217;ve got several comments on Oracle Core to respond to but haven&#8217;t had time to look at them yet. Very briefly, though, I thought I&#8217;d point to a note that Doug Burns has just posted about John Beresniewicz&#8217;s presentation one &#8220;outliers&#8221; at the UKOUG conference.</p>
<p>Key feature: it supplies a query that could be very useful for capturing short, but nasty, events;  and has links to a couple of documents explaining what it&#8217;s trying to do and why. It&#8217;s a query that could do with more exercise on production systems so that Doug can get some feedback to JB about how effect it is, and how it could be improved.</p>
<p><em><strong><a href="http://oracledoug.com/serendipity/index.php?/archives/1669-UKOUG-2011-Ash-Outliers.html">Start here</a></strong></em>.</p>
<p>&nbsp;</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8126/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8126/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8126/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8126&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/11/ash/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>I wish</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/06/i-wish-5/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/06/i-wish-5/#comments</comments>
		<pubDate>Fri, 06 Jan 2012 17:38:21 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[CBO]]></category>
		<category><![CDATA[Execution plans]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Wishlist]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8040</guid>
		<description><![CDATA[A few days ago I published an example of the optimizer failing to handle an updateable join view because it didn&#8217;t recognise that a particular type of aggregate subquery would guarantee key-preservation.  Here&#8217;s another example where the human eye can see key-preservation, but the optimizer can&#8217;t (even in 11.2.0.2). As usual we&#8217;ll start with some [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8040&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>A few days ago I <a href="http://jonathanlewis.wordpress.com/2011/12/29/i-wish-4/"><em><strong>published an example of the optimizer failing</strong></em> </a>to handle an updateable join view because it didn&#8217;t recognise that a particular type of aggregate subquery would guarantee<strong> key-preservation</strong>.  Here&#8217;s another example where the human eye can see key-preservation, but the optimizer can&#8217;t (even in 11.2.0.2). As usual we&#8217;ll start with some sample data &#8211; in this case two tables since I want to update from one table to the other.</p>
<p><pre class="brush: plain; gutter: false;">
create table t1 (
	id1	number,
	id2	number,
	val	number,
	constraint t1_pk primary key (id1, id2)
);

insert into t1 values (1,1,99);
commit;

create table t2 (
	id1	number,
	id2	number,
	id3	number,
	val	number,
	constraint t2_pk primary key (id1, id2, id3)
);

insert into t2 values (1,1,1,200);
insert into t2 values (1,1,2,200);
commit;

</pre></p>
<p>Note, particularly, that <strong>t1</strong> has a two-part key, and <strong>t2</strong> has a three-part key; and it&#8217;s perfectly reasonable to write a query like the following &#8211; and then I might use the query to define a view:</p>
<p><pre class="brush: plain; gutter: false;">
select
	t1.val	v1,
	t2.val	v2
from
	t1,t2
where
	t1.id1 = t2.id1
and	t1.id2 = t2.id2
and	t2.id3 = 1
;
</pre></p>
<p>You&#8217;ll note that table <strong>t2</strong> is key-preserved. If I pick a row from <strong>t2</strong>, I use the primary key of table <strong>t1</strong> to find a match &#8211; so any row that gets picked from <strong>t2</strong> can appear at most once in the result set.</p>
<p>However, although <em>the join itself</em> doesn&#8217;t include all the columns in the primary key of <strong>t2</strong>, table <strong>t1</strong> is also key-preserved in the view. If I pick a row from <strong>t1</strong> the join condition may find several rows in <strong>t2</strong> that match &#8211; but once the predicate<em> t2.id3 = 1</em> is applied this will reduce the possible matches to at most one &#8211; so each row from <strong>t1</strong> can appear at most once in the result set.</p>
<p>So what happens when you try these two updates ?</p>
<p><pre class="brush: plain; gutter: false;">
update
	(
	select
		t1.val	v1,
		t2.val	v2
	from
		t1,t2
	where
		t1.id1 = t2.id1
	and	t1.id2 = t2.id2
	and	t2.id3 = 1
)	iv
set
	iv.v2 = iv.v1
;

update
	(
	select
		t1.val	v1,
		t2.val	v2
	from
		t1,t2
	where
		t1.id1 = t2.id1
	and	t1.id2 = t2.id2
	and	t2.id3 = 1
)	iv
set
	iv.v1 = iv.v2
;

</pre></p>
<p>The first one works, you can update table <strong>t2</strong> through the view; the second one fails with Oracle error <em>&#8220;ORA-01779: cannot modify a column which maps to a non key-preserved table.&#8221;</em></p>
<p>You might want to try something clever with function-based indexes &#8211; after all, if we only want to do this update for the special case where<em> id3 = 1</em> (or perhaps a limited number of special cases) we can create a unique index to help:</p>
<p><pre class="brush: plain; gutter: false;">
create unique index t2_fbi on t2(
	case when id3 = 1 then id1 end,
	case when id3 = 1 then id2 end
);

update
	(
	select
		t1.val	v1,
		t2.val	v2
	from
		t1,t2
	where
		case when t2.id3 = 1 then t2.id1 end = t1.id1
	and	case when t2.id3 = 1 then t2.id2 end = t1.id2
	)	iv
set
	iv.v1 = iv.v2
;

</pre></p>
<p>Even though the execution plan for the underlying query shows Oracle doing a unique scan on a unique index in a nested loop join, the update still fails with Oracle error ORA-01779.</p>
<p>I have to say that I&#8217;m not as disappointed with the example as I was with the aggregate subquery example. The aggregate example looks like a reasonable requirement, this one looks like an application design flaw (essentially, it has the flavour of an application that has stuck several entities into a single table) so I&#8217;ve not worried about it too much in the past.</p>
<p>Recently, though, I&#8217;ve seen an increasing number of people thinking about keeping old copies of data in the same table as the current copy &#8211; and one strategy for this is to have a flag that marks the current copy and uses the FBI trick I&#8217;ve just shown as a way to enforce uniqueness. The side effect may cause problems to a few people.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8040/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8040/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8040/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8040/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8040/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8040/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8040/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8040/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8040&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/06/i-wish-5/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>Index size bug</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/04/index-size-bug/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/04/index-size-bug/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 17:29:54 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[Bugs]]></category>
		<category><![CDATA[dbms_xplan]]></category>
		<category><![CDATA[Indexing]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8077</guid>
		<description><![CDATA[Here&#8217;s a follow-up to a post I did some time ago about estimating the size of an index before you create it. The note describes dbms_stats.create_index_cost() procedure, and how it depends on the results of a call to explain plan. A recent question on the OTN database forum highlighted a bug in explain plan, however, which [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8077&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a follow-up to a post I did some time ago about <em><strong><a href="http://jonathanlewis.wordpress.com/2009/05/22/index-size/">estimating the size of an index</a></strong></em> before you create it. The note describes<em><strong> dbms_stats.create_index_cost()</strong></em> procedure, and how it depends on the results of a call to <em><strong>explain plan</strong></em>. A recent question on the OTN database forum highlighted a bug in <em><strong>explain plan</strong></em>, however, which I can demonstrate very easily. I&#8217;ll start with a small amount of data to demonstrate the basic content that is used to calculate the index cost.</p>
<p><pre class="brush: plain; gutter: false;">
create table t1
as
with generator as (
	select	--+ materialize
		rownum id 
	from dual 
	connect by 
		level &lt;= 10000
)
select
	rownum							n1,
	case when mod(rownum,2) = 0 then rownum end		n2,
	lpad(rownum,10,'0')					v1,
	case when mod(rownum,2) = 0 then rpad('x',10) end	v2,
	rpad('x',100)						padding
from
	generator	v1,
	generator	v2
where
	rownum &lt;= 100000
;

begin
	dbms_stats.gather_table_stats(
		ownname		 =&gt; user,
		tabname		 =&gt;'T1',
		method_opt	 =&gt; 'for all columns size 1'
	);
end;
/

explain plan for
create index t1_v1 on t1(v1);

select * from table(dbms_xplan.display);

</pre></p>
<p>You&#8217;re likely to get some variation on the results below, particularly in the note about the estimated index size, but here&#8217;s the result I got last time I ran the test:</p>
<p><pre class="brush: plain; gutter: false;">
Explained.

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------
Plan hash value: 2170349088

----------------------------------------------------------------
| Id  | Operation              | Name  | Rows  | Bytes | Cost  |
----------------------------------------------------------------
|   0 | CREATE INDEX STATEMENT |       |   100K|  1074K|   286 |
|   1 |  INDEX BUILD NON UNIQUE| T1_V1 |       |       |       |
|   2 |   SORT CREATE INDEX    |       |   100K|  1074K|       |
|   3 |    TABLE ACCESS FULL   | T1    |   100K|  1074K|   278 |
----------------------------------------------------------------

Note
-----
   - cpu costing is off (consider enabling it)
   - estimated index size: 3145K bytes

15 rows selected.

</pre><br />
As you can see, I&#8217;ve got an accurate estimate of the rows that will go into the index, with a reasonably accurate estimate of the total volume of data in the rows (column lengths only) that will go into the index.  The estimated index size then allows for things like rowids, row overhead, pctfree, space management blocks, and extent sizes, resulting in a larger figure (significantly larger in this case given the relatively small length of the column used in the index).</p>
<p>Let&#8217;s repeat the experiment a few times with increasing numbers of rows in the table, though. Rather than give you the full output for each test, I&#8217;ll just produced the Rows and Bytes figure and the estimated size &#8211; the last three sets of figures are a little clue about what&#8217;s gone wrong:<br />
<pre class="brush: plain; gutter: false;">
 Rows      Bytes     Est. Size
 ------    ------    ---------
     1M      10MB         24MB
    10M	    104MB        243MB
   100M	   1049MB       2415MB
  1000M      10GB       2483MB
 10000M     102GB       2818MB
 ------    ------    ---------
   176M    1846MB       4227MB
   177M    1856MB           0B
   180M    1888MB         67MB
 ------    ------    ---------

</pre></p>
<p>It looks like the estimated size is captured as a 32 bit number, so it rolls over to zero at roughly 4.3 billion. The bug is still there in 11.2.0.2, I haven&#8217;t yet checked 10.2.0.5 or 11.2.0.3</p>
<p><strong>Footnote:</strong> Just in case you&#8217;re wondering, I didn&#8217;t actually create a table with 10 billion rows in it, I just used dbms_stats.set_table_stats() to tell Oracle that the table has 10 billion rows.</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8077/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8077/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8077/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8077/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8077/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8077/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8077/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8077/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8077&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/04/index-size-bug/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>NewDensity</title>
		<link>http://jonathanlewis.wordpress.com/2012/01/03/newdensity/</link>
		<comments>http://jonathanlewis.wordpress.com/2012/01/03/newdensity/#comments</comments>
		<pubDate>Tue, 03 Jan 2012 17:56:01 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[CBO]]></category>
		<category><![CDATA[Histograms]]></category>
		<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Statistics]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8061</guid>
		<description><![CDATA[A recent comment on a note I wrote some time ago about faking histograms asked about the calculations of selectivity in the latest versions of Oracle. As I read the question, I realised that I had originally supplied a formula for calculating cardinality, rather than selectivity, so I thought I&#8217;d supply a proper example. We&#8217;ll start with a script [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8061&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>A recent comment on a note I wrote some time ago about<em><strong> <a href="http://jonathanlewis.wordpress.com/2010/03/23/fake-histograms/#comment-43854">faking histograms</a></strong></em> asked about the calculations of <em><strong>selectivity</strong></em> in the latest versions of Oracle. As I read the question, I realised that I had originally supplied a formula for calculating <em><strong>cardinality</strong></em>, rather than <em><strong>selectivity</strong></em>, so I thought I&#8217;d supply a proper example.</p>
<p>We&#8217;ll start with a script to create some data and stats &#8211; and I&#8217;m going to start with a script I wrote in Jan 2001 (which is why it happens to use the <em><strong>analyze </strong></em>command rather than <em><strong>dbms_stats.gather_table_stats</strong></em>, even though this example comes from an instance of 11.2.0.2).</p>
<p><pre class="brush: plain; gutter: false;">
create table t1 (
	skew,	skew2,	padding
)
as
select r1, r2, rpad('x',400)
from
(
	select /*+ no_merge */
		rownum r1
	from all_objects
	where rownum )	v1,
(
	select /*+ no_merge */
		rownum r2
	from all_objects
	where rownum )	v2
where r2 order by r2,r1
;

alter table t1 modify skew not null;
alter table t1 modify skew2 not null;

create index t1_skew on t1(skew);

analyze table t1 compute statistics
	for all indexed columns size 75;

</pre></p>
<p>The way I&#8217;ve created the data set the column <strong>skew</strong> has one row with the value 1, two rows with the value 2, and so on up to 80 rows with the value 80. I&#8217;ve put in a bid to collect a histogram of 75 buckets &#8211; which the default, by the way, for the <strong>analyze </strong>command - on any indexed columns . (Interestingly the resulting histogram on column <em><strong>skew </strong></em>held on 74 buckets.)</p>
<p>To demonstrate the calculation of selectivity, I then enabled the 10053 trace and ran a query to select one of the <em>&#8220;non-popular&#8221;</em> values (i.e. a value with a fairly small number of duplicates). The section of the trace file I want to talk about appears as the &#8220;Single Table Access Path&#8221;.</p>
<p><pre class="brush: plain;">
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for T1[T1]
  Column (#1):
    NewDensity:0.008940, OldDensity:0.006757 BktCnt:74, PopBktCnt:31, PopValCnt:15, NDV:80
  Column (#1): SKEW(
    AvgLen: 2 NDV: 80 Nulls: 0 Density: 0.008940 Min: 1 Max: 80
    Histogram: HtBal  #Bkts: 74  UncompBkts: 74  EndPtVals: 59
  Table: T1  Alias: T1
    Card: Original: 3240.000000  Rounded: 29  Computed: 28.96  Non Adjusted: 28.96
  Access Path: TableScan
    Cost:  32.00  Resp: 32.00  Degree: 0
      Cost_io: 32.00  Cost_cpu: 0
      Resp_io: 32.00  Resp_cpu: 0
  Access Path: index (AllEqRange)
    Index: T1_SKEW
    resc_io: 30.00  resc_cpu: 0
    ix_sel: 0.008940  ix_sel_with_filters: 0.008940
    Cost: 30.00  Resp: 30.00  Degree: 1
  Best:: AccessPath: IndexRange
  Index: T1_SKEW
         Cost: 30.00  Degree: 1  Resp: 30.00  Card: 28.96  Bytes: 0
</pre></p>
<p>A few points to notice on line 4:</p>
<blockquote><p>The <strong>NDV </strong>(number of distinct values) is 80; this means that the Density, in the absence of a histogram, would be 1/80 = 0.0125<br />
We have a <strong>NewDensity </strong>and an <strong>OldDensity</strong>. The <strong>OldDensity </strong>is the value that would have been reported simply as <strong>Density </strong>in 10g or 9i, and is derived using the mechanism I described in <em>&#8220;Cost Based Oracle &#8211; Fundamentals&#8221;</em> a few years ago. Informally this was:</p>
<blockquote><p>sum of the square of the frequency of the non-popular values /<br />
(number of non-null rows * number of non-popular non-null rows)</p></blockquote>
</blockquote>
<p>This formula for <strong>OldDensity</strong> is (I assume) a fairly subtle formula based on expected number of rows for a randomly selected non-popular value in the presence of popular values. The <strong>NewDensity</strong>, however, seems to take the much simpler approach of &#8220;factoring out&#8221; the popular values. There are two ways you can approach the arithmetic &#8211; one is by thinking of the number of rows you expect for the query <em>&#8220;column = &#8216;non-popular value&#8217;&#8221;,</em> the other is by thinking of the number of non-popuar values and then adjusting for the relative volume of non-popular value in the table.</p>
<h3>Option 1: Cardinality.</h3>
<p>Line 9 tells us there are 3240 rows in the table.<br />
Line 4 tells us there are 80 (NDV) distinct values of which 15 (PopValCnt) are popular, and 74 (BktCnt) buckets of which 31 (PopBktCnt) contain popular values.<br />
From this we determine that there are (80 &#8211; 15 = ) 65 non-popular values and (3240 * (74-31)/74 = ) 1883 non-popular rows.<br />
Hence we infer that a typical non-popular value will report (1883 / 65 = ) 29 rows &#8211; which is the rounded cardinality we see in line 9.</p>
<h3>Option 2: Selectivity.</h3>
<p>If we consider only non-popular values, then the selectivity is 1/(number of non-popular values) = 1/65.<br />
But this selectivity applies to only 43 buckets of the 74 total bucket count.<br />
To generate a selectivity that can be applied to the original cardinality of the table we have to scale it accordingly.<br />
The selectivity, labelled the <strong>NewDensity</strong>, is (1/65) * (43/74) = 0.00894 &#8211; which is the value we see in line 4.<br />
(Following this, of course, the cardinality for <em>&#8216;column = constant&#8217;</em> would be 3,240 * 0.00894 = 29</p>
<p><strong>Footnote 1:</strong><br />
I have been a little cavalier with rounding throughout the example, just to keep the numbers looking a little tidier.<br />
<strong>Footnote 2:</strong><br />
If the column is allowed to be null then our calculation of cardinality would use (3,240 &#8211; number of nulls) instead of 3,240. The method for calculating the selectivity would not change, but the resulting figure would be applied to (3,240 &#8211; number of nulls).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8061/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8061/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8061/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8061/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8061/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8061/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8061/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8061/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8061&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2012/01/03/newdensity/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
		<item>
		<title>FBI Bug</title>
		<link>http://jonathanlewis.wordpress.com/2011/12/30/fbi-bug-2/</link>
		<comments>http://jonathanlewis.wordpress.com/2011/12/30/fbi-bug-2/#comments</comments>
		<pubDate>Fri, 30 Dec 2011 17:47:59 +0000</pubDate>
		<dc:creator>Jonathan Lewis</dc:creator>
				<category><![CDATA[Bugs]]></category>
		<category><![CDATA[Execution plans]]></category>
		<category><![CDATA[Function based indexes]]></category>
		<category><![CDATA[Indexing]]></category>
		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://jonathanlewis.wordpress.com/?p=8043</guid>
		<description><![CDATA[Here&#8217;s a funny little optimizer bug &#8211; though one that seems to have been fixed by at least 10.2.0.3. It showed up earlier on today in a thread on the OTN database forum. We&#8217;ll start (in 9.2.0.8) with a little table and two indexes &#8211; one normal, the other descending. You&#8217;ll notice that the two [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8043&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a funny little optimizer bug &#8211; though one that seems to have been fixed by at least 10.2.0.3. It showed up earlier on today in a<em><strong><a href="https://forums.oracle.com/forums/thread.jspa?threadID=2327413&amp;tstart=0"> thread on the OTN database forum</a></strong></em>. We&#8217;ll start (in 9.2.0.8) with a little table and two indexes &#8211; one normal, the other descending.</p>
<p><pre class="brush: plain; gutter: false;">
create table t1
as
with generator as (
	select	--+ materialize
		rownum id 
	from dual 
	connect by 
		level &lt;= 10000
)
select
	rownum			id,
	lpad(rownum,10,'0')	small_vc,
	rpad('x',100)		padding
from
	generator	v1,
	generator	v2
where
	rownum &lt;= 10000
;

-- collect stats

create index t1_id_asc  on t1(id) compute statistics;
create index t1_id_desc on t1(id desc) compute statistics;

</pre><br />
You&#8217;ll notice that the two indexes are on the same column, even though one of them has (redundantly) declared the column to be treated in descending order. If I now execute the following query, noting the hint to use index <strong>t1_id_asc</strong>, would you expect the presence of index <strong>t1_id_desc </strong>to make any difference to the plan ?</p>
<p><pre class="brush: plain; gutter: false;">
select 
	/*+ index(t1 t1_id_asc) */
	* 
from 
	t1
where
	id between 1001 and 2000
;
</pre></p>
<p>Here are the plans, first with <strong>t1_id_desc</strong> in place:<br />
<pre class="brush: plain; gutter: false;">
---------------------------------------------------------------------------
| Id  | Operation                   |  Name       | Rows  | Bytes | Cost  |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |     3 |   342 |     5 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1          |     3 |   342 |     5 |
|*  2 |   INDEX RANGE SCAN          | T1_ID_ASC   |     3 |       |     4 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(&quot;T1&quot;.&quot;ID&quot;&gt;=1001 AND &quot;T1&quot;.&quot;ID&quot;&lt;=2000)
       filter(SYS_OP_DESCEND(&quot;T1&quot;.&quot;ID&quot;)&lt;=HEXTORAW('3DF4FDFF')  AND
              SYS_OP_DESCEND(&quot;T1&quot;.&quot;ID&quot;)&gt;=HEXTORAW('3DEAFF') )

</pre></p>
<p>Now after dropping index <strong>t1_id_desc</strong></p>
<p><pre class="brush: plain; gutter: false;">
---------------------------------------------------------------------------
| Id  | Operation                   |  Name       | Rows  | Bytes | Cost  |
---------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |  1001 |   111K|    22 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1          |  1001 |   111K|    22 |
|*  2 |   INDEX RANGE SCAN          | T1_ID_ASC   |  1001 |       |     4 |
---------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access(&quot;T1&quot;.&quot;ID&quot;&gt;=1001 AND &quot;T1&quot;.&quot;ID&quot;&lt;=2000)

</pre></p>
<p>The shape of the two plans hasn&#8217;t changed, of course, they&#8217;ve both obeyed my hint. Notice, however, the changes in the Predicate Information and the estimated cardinalities. With index <strong>t1_id_desc</strong> in place, the optimizer has found the definition of the hidden column representing the <em>&#8220;id desc&#8221;</em> and used it to generate some new predicates, introducing some extra factors into the calculation of selectivity.</p>
<p>In the case of the OTN query, the initial inputs were bind variables &#8211; which meant the new predicates looked like:<br />
<pre class="brush: plain; gutter: false;">
       filter(SYS_OP_DESCEND(&quot;D&quot;.&quot;CREATEDAT&quot;)&lt;=SYS_OP_DESCEND(:Z) AND
              SYS_OP_DESCEND(&quot;D&quot;.&quot;CREATEDAT&quot;)&gt;=SYS_OP_DESCEND(:Z))
</pre></p>
<p>In this version of Oracle this resulted in the predicates being treated as <em><strong><a href="http://jonathanlewis.wordpress.com/2010/09/07/cbo-surprise-3/">&#8220;guesses on an index range scan&#8221;</a></strong></em> &#8211; which resulted in the optimizer ignoring the appropriate index (until hinted) even though the cost calculation gave a lower cost.</p>
<p><strong>Update 31 Dec 2011:</strong> It&#8217;s just occurred to me that this is another example of a case where you can drop an index that isn&#8217;t being used and find that execution plans can change as a side effect.  (Conversely, you create and index that should change any execution plans &#8211; and some plans change, even though they don&#8217;t use the index.) Luckily, as I pointed out above, this demo came from 9.2.0.8, and the behaviour has been fixed by 10.2.0.3 (and possible earlier).</p>
<br />  <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/jonathanlewis.wordpress.com/8043/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/jonathanlewis.wordpress.com/8043/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/jonathanlewis.wordpress.com/8043/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/jonathanlewis.wordpress.com/8043/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/jonathanlewis.wordpress.com/8043/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/jonathanlewis.wordpress.com/8043/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/jonathanlewis.wordpress.com/8043/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/jonathanlewis.wordpress.com/8043/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=jonathanlewis.wordpress.com&amp;blog=491988&amp;post=8043&amp;subd=jonathanlewis&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://jonathanlewis.wordpress.com/2011/12/30/fbi-bug-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/08b4eccce68cd521b54671abb0442ae1?s=96&#38;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96&#38;r=G" medium="image">
			<media:title type="html">Jonathan Lewis</media:title>
		</media:content>
	</item>
	</channel>
</rss>
