<?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: Full Table Scans and the Buffer Cache in 11.2 &#8211; What is Wrong with this Quote?</title>
	<atom:link href="http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/feed/" rel="self" type="application/rss+xml" />
	<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/</link>
	<description>Miscellaneous Random Oracle Topics: Stop, Think, ... Understand</description>
	<lastBuildDate>Thu, 23 May 2013 04:02:42 +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/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4613</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Thu, 12 Apr 2012 23:04:13 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4613</guid>
		<description><![CDATA[Mich,

Sorry again for the delay in my response.  It seems that I am having a bit of difficulty finding time to respond to comments lately due to a number of non-Oracle related activities.  Windows Update is broken on a relative&#039;s computer, and as a side effect, I cannot install the latest version of the virus scanner brand that I have used since 1995.  I have been fighting that problem for almost a week.  Lots of other non-Oracle computer related things too.

---

&lt;i&gt;Hanging head in shame&lt;/i&gt; I have not yet had a chance to read the book that Steve Adams wrote.  I did manage to find his book in the Google Books library:
http://books.google.com/books?id=KG4j7NuHbRsC&amp;pg=PA28

What is shown in the Google Books library seems to indicate that your quote above is a paraphrase of the book - not necessarily a bad paraphrase.  For instance, the last sentence on page 29 states ( http://books.google.com/books?id=KG4j7NuHbRsC&amp;pg=PA29 ):
&lt;blockquote&gt;
&quot;In general, if this rule is broken, an ORA-600 [504] internal error is raised.&quot;
&lt;/blockquote&gt;

The description of your problem regarding deadlocking on indexes seems to point a little more directly at enqueues (locks) rather than latches (I could of course be completely wrong).  Jonathan Lewis took an advanced look at the differences between enqueues and latches in his recent &quot;Oracle Core&quot; book:
http://books.google.com/books?id=G9AJA91PL54C&amp;pg=PA59

The AskTom site has also covered the differences between latches and enqueues several times (you may not be able to click this link):
http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:10899066672589

In Oracle Database 10.1 some types of latches started to be replaced with mutexes (I think that Tanel Poder mentioned specific latches on his blog), are more were replaced in 10.2, 11.1, and 11.2.  What was absolutely true about Oracle Database latching back in 1999, may have changed over the course of the last 13 years.]]></description>
		<content:encoded><![CDATA[<p>Mich,</p>
<p>Sorry again for the delay in my response.  It seems that I am having a bit of difficulty finding time to respond to comments lately due to a number of non-Oracle related activities.  Windows Update is broken on a relative&#8217;s computer, and as a side effect, I cannot install the latest version of the virus scanner brand that I have used since 1995.  I have been fighting that problem for almost a week.  Lots of other non-Oracle computer related things too.</p>
<p>&#8212;</p>
<p><i>Hanging head in shame</i> I have not yet had a chance to read the book that Steve Adams wrote.  I did manage to find his book in the Google Books library:<br />
<a href="http://books.google.com/books?id=KG4j7NuHbRsC&#038;pg=PA28" rel="nofollow">http://books.google.com/books?id=KG4j7NuHbRsC&#038;pg=PA28</a></p>
<p>What is shown in the Google Books library seems to indicate that your quote above is a paraphrase of the book &#8211; not necessarily a bad paraphrase.  For instance, the last sentence on page 29 states ( <a href="http://books.google.com/books?id=KG4j7NuHbRsC&#038;pg=PA29" rel="nofollow">http://books.google.com/books?id=KG4j7NuHbRsC&#038;pg=PA29</a> ):</p>
<blockquote><p>
&#8220;In general, if this rule is broken, an ORA-600 [504] internal error is raised.&#8221;
</p></blockquote>
<p>The description of your problem regarding deadlocking on indexes seems to point a little more directly at enqueues (locks) rather than latches (I could of course be completely wrong).  Jonathan Lewis took an advanced look at the differences between enqueues and latches in his recent &#8220;Oracle Core&#8221; book:<br />
<a href="http://books.google.com/books?id=G9AJA91PL54C&#038;pg=PA59" rel="nofollow">http://books.google.com/books?id=G9AJA91PL54C&#038;pg=PA59</a></p>
<p>The AskTom site has also covered the differences between latches and enqueues several times (you may not be able to click this link):<br />
<a href="http://asktom.oracle.com/pls/apex/f?p=100:11:0" rel="nofollow">http://asktom.oracle.com/pls/apex/f?p=100:11:0</a>::::P11_QUESTION_ID:10899066672589</p>
<p>In Oracle Database 10.1 some types of latches started to be replaced with mutexes (I think that Tanel Poder mentioned specific latches on his blog), are more were replaced in 10.2, 11.1, and 11.2.  What was absolutely true about Oracle Database latching back in 1999, may have changed over the course of the last 13 years.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mich Talebzadeh</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4609</link>
		<dc:creator><![CDATA[Mich Talebzadeh]]></dc:creator>
		<pubDate>Tue, 10 Apr 2012 08:18:03 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4609</guid>
		<description><![CDATA[Index hash join

I am referring to Charles table at the beginning of this thread (table t1). A while back I was testing it. The table I have is practically the same as below
&lt;pre&gt;
CREATE TABLE t1 AS
SELECT
ROWNUM k1,
DECODE(ROWNUM,1,1,0) c,
LPAD(&#039;A&#039;,255,&#039;A&#039;) c3
FROM
DUAL
CONNECT BY
LEVELUSER,TABNAME=&gt;&#039;T1&#039;,CASCADE=&gt;TRUE)
&lt;/pre&gt;
I run in as
&lt;pre&gt;
ALTER SESSION SET TRACEFILE_IDENTIFIER = &#039;test_t1_with_trace&#039;;
EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE ( waits=&gt;true, plan_stat=&gt;&#039;ALL_EXECUTIONS&#039; );
SELECT k1, c FROM t1 WHERE c  0;
&lt;/pre&gt;

tkprof output shows:
&lt;pre&gt;
SELECT k1, c
FROM
 t1 WHERE c != 0


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.08          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.17       0.35       3911       3930          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.18       0.44       3911       3930          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 97

Rows     Row Source Operation
-------  ---------------------------------------------------
      1  VIEW  index$_join$_001 (cr=3930 pr=3911 pw=0 time=0 us cost=6388 size=8 card=1)
      1   HASH JOIN  (cr=3930 pr=3911 pw=0 time=0 us)
      1    INDEX FAST FULL SCAN IND_T1_C (cr=1826 pr=1818 pw=0 time=0 us cost=2276 size=8 card=1)(object id 87301)
1000000    INDEX FAST FULL SCAN IND_T1_K1 (cr=2104 pr=2093 pw=0 time=622503 us cost=2621 size=8 card=1)(object id 87300)
&lt;/pre&gt;
Now that index IND_T1_K1 is a unique index and we know that IND_T1_C has one row that qualifies for c != 0. However, it chooses the 1,000,000 row resultset as the build stream and 1 row resultset as the probe stream. This dores not look correct unless some role reversal is happening after?

Mich]]></description>
		<content:encoded><![CDATA[<p>Index hash join</p>
<p>I am referring to Charles table at the beginning of this thread (table t1). A while back I was testing it. The table I have is practically the same as below</p>
<pre>
CREATE TABLE t1 AS
SELECT
ROWNUM k1,
DECODE(ROWNUM,1,1,0) c,
LPAD('A',255,'A') c3
FROM
DUAL
CONNECT BY
LEVELUSER,TABNAME=&gt;'T1',CASCADE=&gt;TRUE)
</pre>
<p>I run in as</p>
<pre>
ALTER SESSION SET TRACEFILE_IDENTIFIER = 'test_t1_with_trace';
EXEC DBMS_MONITOR.SESSION_TRACE_ENABLE ( waits=&gt;true, plan_stat=&gt;'ALL_EXECUTIONS' );
SELECT k1, c FROM t1 WHERE c  0;
</pre>
<p>tkprof output shows:</p>
<pre>
SELECT k1, c
FROM
 t1 WHERE c != 0


call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.08          0          0          0           0
Execute      1      0.00       0.00          0          0          0           0
Fetch        2      0.17       0.35       3911       3930          0           1
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total        4      0.18       0.44       3911       3930          0           1

Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 97

Rows     Row Source Operation
-------  ---------------------------------------------------
      1  VIEW  index$_join$_001 (cr=3930 pr=3911 pw=0 time=0 us cost=6388 size=8 card=1)
      1   HASH JOIN  (cr=3930 pr=3911 pw=0 time=0 us)
      1    INDEX FAST FULL SCAN IND_T1_C (cr=1826 pr=1818 pw=0 time=0 us cost=2276 size=8 card=1)(object id 87301)
1000000    INDEX FAST FULL SCAN IND_T1_K1 (cr=2104 pr=2093 pw=0 time=622503 us cost=2621 size=8 card=1)(object id 87300)
</pre>
<p>Now that index IND_T1_K1 is a unique index and we know that IND_T1_C has one row that qualifies for c != 0. However, it chooses the 1,000,000 row resultset as the build stream and 1 row resultset as the probe stream. This dores not look correct unless some role reversal is happening after?</p>
<p>Mich</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mich Talebzadeh</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4608</link>
		<dc:creator><![CDATA[Mich Talebzadeh]]></dc:creator>
		<pubDate>Mon, 09 Apr 2012 22:51:11 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4608</guid>
		<description><![CDATA[Charles,

Your point on &quot;The deadlock on indexes that you mention – might that just be a sign of two sessions trying to insert rows with the same primary key value into two different tables?&quot;

Slighlly more interesting than that. The same proc running with two different sets of parameters trying to do update on the same table with one normal b-tree index. The issue is that the proc was doing multiple updates and depending on the set size (chosen by parameters) at part of the code was doing a table scan and other parts were using the index. THe deadlock was one instance of proc doing a table scan and the other was using the index (much smaller result set). 

Steve Adams in his book p 28-29 mentions to the effect that

&quot;Oracle expects latches to be held only briefly and intermittently. Otherwise if the use of latch is not brief or intermittent then there can be contention (remember they do not allow multiple processes to inspect the protected data concurrently). It makes sense to expect that a single Oracle process to hold a number of latches concurrently. Therefore there is a possibility of latching deadlock occurring. One process holding latch A and another thread holding latch B and both processes spinning [on their semaphore] and waiting for the alternate latch.  Oracle ensures that this cannot happen by ensuring that latches are always taken in a defined order when more than one latch is needed. To support this, Oracle must maintain different latch levels. When a process attempts to get a latch, a check is made to ensure that it is not already holding a latch of the same level or latch of higher level. A process that needs a higher level latch has to sleep while holding a lower level latch. In this scenario, the lower level latches are held much longer than normal. In general if this happens, it can result in a deadlock.&quot;

Interesting point but still investigating it.

Mich]]></description>
		<content:encoded><![CDATA[<p>Charles,</p>
<p>Your point on &#8220;The deadlock on indexes that you mention – might that just be a sign of two sessions trying to insert rows with the same primary key value into two different tables?&#8221;</p>
<p>Slighlly more interesting than that. The same proc running with two different sets of parameters trying to do update on the same table with one normal b-tree index. The issue is that the proc was doing multiple updates and depending on the set size (chosen by parameters) at part of the code was doing a table scan and other parts were using the index. THe deadlock was one instance of proc doing a table scan and the other was using the index (much smaller result set). </p>
<p>Steve Adams in his book p 28-29 mentions to the effect that</p>
<p>&#8220;Oracle expects latches to be held only briefly and intermittently. Otherwise if the use of latch is not brief or intermittent then there can be contention (remember they do not allow multiple processes to inspect the protected data concurrently). It makes sense to expect that a single Oracle process to hold a number of latches concurrently. Therefore there is a possibility of latching deadlock occurring. One process holding latch A and another thread holding latch B and both processes spinning [on their semaphore] and waiting for the alternate latch.  Oracle ensures that this cannot happen by ensuring that latches are always taken in a defined order when more than one latch is needed. To support this, Oracle must maintain different latch levels. When a process attempts to get a latch, a check is made to ensure that it is not already holding a latch of the same level or latch of higher level. A process that needs a higher level latch has to sleep while holding a lower level latch. In this scenario, the lower level latches are held much longer than normal. In general if this happens, it can result in a deadlock.&#8221;</p>
<p>Interesting point but still investigating it.</p>
<p>Mich</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4607</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Mon, 09 Apr 2012 17:05:01 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4607</guid>
		<description><![CDATA[Mich,

I had heard previously that most of the overhead associated with setting the STATISTICS_LEVEL to all is associated with system calls to obtain the current time of day (gettimeofday).  This particular issue is mentioned in Metalink (MOS) Doc ID 436797.1, and seems to be more severe prior to Oracle Database 11.1.  There is a summary in the &quot;Expert Oracle Practices&quot; book on page 313 that demonstates the impact of the TYPICAL and ALL values of STATISTICS_LEVEL for a SQL statement that performs a large number of nested loops joins:
http://books.google.com/books?id=tUNtyMCwDWQC&amp;pg=PA313

I will have to look into the increase of of the number of latch gets with STATISTICS_LEVEL=ALL - I had not considered latching as a potential threat.

The deadlock on indexes that you mention - might that just be a sign of two sessions trying to insert rows with the same primary key value into two different tables?]]></description>
		<content:encoded><![CDATA[<p>Mich,</p>
<p>I had heard previously that most of the overhead associated with setting the STATISTICS_LEVEL to all is associated with system calls to obtain the current time of day (gettimeofday).  This particular issue is mentioned in Metalink (MOS) Doc ID 436797.1, and seems to be more severe prior to Oracle Database 11.1.  There is a summary in the &#8220;Expert Oracle Practices&#8221; book on page 313 that demonstates the impact of the TYPICAL and ALL values of STATISTICS_LEVEL for a SQL statement that performs a large number of nested loops joins:<br />
<a href="http://books.google.com/books?id=tUNtyMCwDWQC&#038;pg=PA313" rel="nofollow">http://books.google.com/books?id=tUNtyMCwDWQC&#038;pg=PA313</a></p>
<p>I will have to look into the increase of of the number of latch gets with STATISTICS_LEVEL=ALL &#8211; I had not considered latching as a potential threat.</p>
<p>The deadlock on indexes that you mention &#8211; might that just be a sign of two sessions trying to insert rows with the same primary key value into two different tables?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mich Talebzadeh</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4606</link>
		<dc:creator><![CDATA[Mich Talebzadeh]]></dc:creator>
		<pubDate>Mon, 09 Apr 2012 15:41:50 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4606</guid>
		<description><![CDATA[Hi Charles, 

Many thanks for your explanation. I have come to conclusion that your point about prefetch not being asynchronous is valid, although I still think with full table scan and index fast full scan where Oracle reads the index as if it were a table using multiblock IO, does not read it in sorted order there is some asynchronous prefteching going on.

I was actually looking at an issue of deadlock on indexes with two procs running at the same time and browsing Steve Adams internal book on latches etc and came across an statement that with STATISTICS_LEVEL = ALL, there are far more latches that Oracle takes. In contrast, it appears that when the parameter is set to TYPICAL (the default), the rowsource/plan execution statistics are disabled. With statistics level = all, a typical query runs many times slower and I gather it is due to system overheads. Although I have not seen any particular explanation for it except that do not use STATISTICS_LEVEL = ALL unless you have to!

Cheers,

Mich]]></description>
		<content:encoded><![CDATA[<p>Hi Charles, </p>
<p>Many thanks for your explanation. I have come to conclusion that your point about prefetch not being asynchronous is valid, although I still think with full table scan and index fast full scan where Oracle reads the index as if it were a table using multiblock IO, does not read it in sorted order there is some asynchronous prefteching going on.</p>
<p>I was actually looking at an issue of deadlock on indexes with two procs running at the same time and browsing Steve Adams internal book on latches etc and came across an statement that with STATISTICS_LEVEL = ALL, there are far more latches that Oracle takes. In contrast, it appears that when the parameter is set to TYPICAL (the default), the rowsource/plan execution statistics are disabled. With statistics level = all, a typical query runs many times slower and I gather it is due to system overheads. Although I have not seen any particular explanation for it except that do not use STATISTICS_LEVEL = ALL unless you have to!</p>
<p>Cheers,</p>
<p>Mich</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4598</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Mon, 02 Apr 2012 11:54:27 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4598</guid>
		<description><![CDATA[Mich,

Sorry again for the delayed response - I have been preoccupied with non-Oracle Database items lately.

I am not sure that I would classify prefetching as an asynchronous operation - that could cause a bit of confusion.  Asynchronous I/O is controlled by the DISK_ASYNCH_IO parameter (and the FILESYSTEMIO_OPTIONS parameter):
http://docs.oracle.com/cd/E11882_01/server.112/e10803/config_db.htm#BGBIHHBD
As shown at the above web page, the V$IOSTAT_FILE view may be queried to determine if asynchronous I/O is enabled for various file types.  A slightly modified version of the SQL statement executed on a 11.2.0.2 Windows database instance:
&lt;pre&gt;
SELECT DISTINCT
  FILETYPE_NAME,
  ASYNCH_IO
FROM
  V$IOSTAT_FILE
ORDER BY
  FILETYPE_NAME;
 
FILETYPE_NAME                ASYNCH_IO
---------------------------- ---------
Archive Log                  ASYNC_OFF
Archive Log Backup           ASYNC_OFF
Control File                 ASYNC_OFF
Data File                    ASYNC_ON
Data File Backup             ASYNC_OFF
Data File Copy               ASYNC_OFF
Data File Incremental Backup ASYNC_OFF
Data Pump Dump File          ASYNC_OFF
Flashback Log                ASYNC_OFF
Log File                     ASYNC_OFF
Other                        ASYNC_OFF
Temp File                    ASYNC_ON
&lt;/pre&gt;

The primary reason why I do not consider prefetching to be an asynchronous operation is because the Oracle process requires one or more of the requested blocks from disk in order to continue processing (unless there are exceptions that I am not considering) - processing for the process halts until the required block is read from disk.  Some people will argue that reading a block from memory is 1000 times faster than reading the same block from disk (others will argue that it is closer to 100 times faster due to all of the code that executes during a logical read) - this speed difference, coupled with the fact that something provoked the Oracle process to request the pre-fetched blocks from disk (maybe one of the 16 blocks read is known to be required), means that the session&#039;s process likely is not number crunching asynchronously while a block read request completes.

It is not sufficient to state that dirty buffers require undo to be applied - a dirty buffer is a block that was modified since being read from disk.  The data block could have been written to the datafiles when there were uncommitted changes in the block.  Undo is stored in a tablespace, just like the regular table and index blocks, and the undo blocks also share the buffer cache with the regular table and index blocks.  The requirement to apply undo to logically roll a block back to a specific SCN does not necessarily require an additional physical I/O.]]></description>
		<content:encoded><![CDATA[<p>Mich,</p>
<p>Sorry again for the delayed response &#8211; I have been preoccupied with non-Oracle Database items lately.</p>
<p>I am not sure that I would classify prefetching as an asynchronous operation &#8211; that could cause a bit of confusion.  Asynchronous I/O is controlled by the DISK_ASYNCH_IO parameter (and the FILESYSTEMIO_OPTIONS parameter):<br />
<a href="http://docs.oracle.com/cd/E11882_01/server.112/e10803/config_db.htm#BGBIHHBD" rel="nofollow">http://docs.oracle.com/cd/E11882_01/server.112/e10803/config_db.htm#BGBIHHBD</a><br />
As shown at the above web page, the V$IOSTAT_FILE view may be queried to determine if asynchronous I/O is enabled for various file types.  A slightly modified version of the SQL statement executed on a 11.2.0.2 Windows database instance:</p>
<pre>
SELECT DISTINCT
  FILETYPE_NAME,
  ASYNCH_IO
FROM
  V$IOSTAT_FILE
ORDER BY
  FILETYPE_NAME;
 
FILETYPE_NAME                ASYNCH_IO
---------------------------- ---------
Archive Log                  ASYNC_OFF
Archive Log Backup           ASYNC_OFF
Control File                 ASYNC_OFF
Data File                    ASYNC_ON
Data File Backup             ASYNC_OFF
Data File Copy               ASYNC_OFF
Data File Incremental Backup ASYNC_OFF
Data Pump Dump File          ASYNC_OFF
Flashback Log                ASYNC_OFF
Log File                     ASYNC_OFF
Other                        ASYNC_OFF
Temp File                    ASYNC_ON
</pre>
<p>The primary reason why I do not consider prefetching to be an asynchronous operation is because the Oracle process requires one or more of the requested blocks from disk in order to continue processing (unless there are exceptions that I am not considering) &#8211; processing for the process halts until the required block is read from disk.  Some people will argue that reading a block from memory is 1000 times faster than reading the same block from disk (others will argue that it is closer to 100 times faster due to all of the code that executes during a logical read) &#8211; this speed difference, coupled with the fact that something provoked the Oracle process to request the pre-fetched blocks from disk (maybe one of the 16 blocks read is known to be required), means that the session&#8217;s process likely is not number crunching asynchronously while a block read request completes.</p>
<p>It is not sufficient to state that dirty buffers require undo to be applied &#8211; a dirty buffer is a block that was modified since being read from disk.  The data block could have been written to the datafiles when there were uncommitted changes in the block.  Undo is stored in a tablespace, just like the regular table and index blocks, and the undo blocks also share the buffer cache with the regular table and index blocks.  The requirement to apply undo to logically roll a block back to a specific SCN does not necessarily require an additional physical I/O.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Mich Talebzadeh</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4594</link>
		<dc:creator><![CDATA[Mich Talebzadeh]]></dc:creator>
		<pubDate>Thu, 29 Mar 2012 00:55:50 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4594</guid>
		<description><![CDATA[Charles,

Many thanks as usual for your analysis. 

It seems that I am hearing more gurus using the term multi-block IO is prefetching and I believe every DBMS that does prefetching does so asynchronously. So I wish we could use asynchronous prefetch as the naming convention :-)
So we have now established that with full table scans and fast full index scans, Oracle will deploy prefetching where it can. So there is obviously a part of execution engine that does the prefetching and there is another part that does the query work? 

When the query part of the execution engine (is this correct?) gets to the block needed and it is not there, then it has to wait. That block could already be a dirty buffer. In that case, I assume that it will have to go to undo to get that block which will incur an additional physical io?

Mich]]></description>
		<content:encoded><![CDATA[<p>Charles,</p>
<p>Many thanks as usual for your analysis. </p>
<p>It seems that I am hearing more gurus using the term multi-block IO is prefetching and I believe every DBMS that does prefetching does so asynchronously. So I wish we could use asynchronous prefetch as the naming convention <img src='http://s0.wp.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /><br />
So we have now established that with full table scans and fast full index scans, Oracle will deploy prefetching where it can. So there is obviously a part of execution engine that does the prefetching and there is another part that does the query work? </p>
<p>When the query part of the execution engine (is this correct?) gets to the block needed and it is not there, then it has to wait. That block could already be a dirty buffer. In that case, I assume that it will have to go to undo to get that block which will incur an additional physical io?</p>
<p>Mich</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4591</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Tue, 27 Mar 2012 11:16:25 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4591</guid>
		<description><![CDATA[Mich,

Sorry for the delay in response.

After reading the following blog article, I am a bit more inclined to agree with your statement that multi-block IO is prefetching by definition:
http://oracle-randolf.blogspot.com/2011/07/logical-io-evolution-part-2-9i-10g.html

However, by extension of the same definition (&quot;multi-block IO is prefetching by definition&quot;), reading an entire 8KB database block (when only the first row in the block is currently of interest) could also be considered &quot;prefetching by definition&quot;. ;-)

Your second point might need a little clarification because logical IOs may or may not result in physical IOs.  It might be more accurate to state that multi-block reads help reduce the average time to access each block when physical block reads are required - this is especially true if hard drive heads must be repositioned (or the required delay of waiting for the hard drive platter to spin around again - 0.004 seconds for a 15,000 RPM drive).  With a multi-block read (when physical hard drives are used, with no built-in read ahead cache), most of the latency in the multi-block physical read (assuming a db file scattered read or direct path read) occurs when accessing the first block, while the rest of the blocks accessed in the single read request are obtained *mostly* with very little additional latency.

Some hard drives (and drive controllers) have special algorithms to reduce hard drive head movement (and rotational) latency when multiple block requests are in the read/write queue (sometimes called native command queuing).  It seems that non-logically-adjacent blocks that are prefetched with DB FILE PARALLEL READ through a prefetch operation are designed to leverage the read/write command queuing algorithms to reduce the average physical block read time: http://docs.oracle.com/cd/E11882_01/server.112/e17110/waitevents003.htm#autoId30

There are probably better (and more accurate) ways to state the above.]]></description>
		<content:encoded><![CDATA[<p>Mich,</p>
<p>Sorry for the delay in response.</p>
<p>After reading the following blog article, I am a bit more inclined to agree with your statement that multi-block IO is prefetching by definition:<br />
<a href="http://oracle-randolf.blogspot.com/2011/07/logical-io-evolution-part-2-9i-10g.html" rel="nofollow">http://oracle-randolf.blogspot.com/2011/07/logical-io-evolution-part-2-9i-10g.html</a></p>
<p>However, by extension of the same definition (&#8220;multi-block IO is prefetching by definition&#8221;), reading an entire 8KB database block (when only the first row in the block is currently of interest) could also be considered &#8220;prefetching by definition&#8221;. <img src='http://s1.wp.com/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>
<p>Your second point might need a little clarification because logical IOs may or may not result in physical IOs.  It might be more accurate to state that multi-block reads help reduce the average time to access each block when physical block reads are required &#8211; this is especially true if hard drive heads must be repositioned (or the required delay of waiting for the hard drive platter to spin around again &#8211; 0.004 seconds for a 15,000 RPM drive).  With a multi-block read (when physical hard drives are used, with no built-in read ahead cache), most of the latency in the multi-block physical read (assuming a db file scattered read or direct path read) occurs when accessing the first block, while the rest of the blocks accessed in the single read request are obtained *mostly* with very little additional latency.</p>
<p>Some hard drives (and drive controllers) have special algorithms to reduce hard drive head movement (and rotational) latency when multiple block requests are in the read/write queue (sometimes called native command queuing).  It seems that non-logically-adjacent blocks that are prefetched with DB FILE PARALLEL READ through a prefetch operation are designed to leverage the read/write command queuing algorithms to reduce the average physical block read time: <a href="http://docs.oracle.com/cd/E11882_01/server.112/e17110/waitevents003.htm#autoId30" rel="nofollow">http://docs.oracle.com/cd/E11882_01/server.112/e17110/waitevents003.htm#autoId30</a></p>
<p>There are probably better (and more accurate) ways to state the above.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: talebzadeh</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4590</link>
		<dc:creator><![CDATA[talebzadeh]]></dc:creator>
		<pubDate>Sun, 25 Mar 2012 20:55:26 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4590</guid>
		<description><![CDATA[Hi Charles,

Thank you for your explanation and example. I think multi-block IO *is* prefetching by definition. So I still have this point if I may

Now wiyh multi-block IO by time the query engine gets to that block it is a kind of logical IO as opposed to physical IO?
 
That means that Oracle dispatches the IO request *ahead* of when it is actually needed. So the only time it has to wait for a prefetched block is when it gets to a block that should have been there for multi-block IO and it had not been prefetched yet. So the whole idea of a multi-block IO  is to asynchronously prefetch blocks so that when the query engine gets to that block, it is a logical IO vs. a physical IO?
 
Mich]]></description>
		<content:encoded><![CDATA[<p>Hi Charles,</p>
<p>Thank you for your explanation and example. I think multi-block IO *is* prefetching by definition. So I still have this point if I may</p>
<p>Now wiyh multi-block IO by time the query engine gets to that block it is a kind of logical IO as opposed to physical IO?</p>
<p>That means that Oracle dispatches the IO request *ahead* of when it is actually needed. So the only time it has to wait for a prefetched block is when it gets to a block that should have been there for multi-block IO and it had not been prefetched yet. So the whole idea of a multi-block IO  is to asynchronously prefetch blocks so that when the query engine gets to that block, it is a logical IO vs. a physical IO?</p>
<p>Mich</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Charles Hooper</title>
		<link>http://hoopercharles.wordpress.com/2012/02/26/full-table-scans-and-the-buffer-cache-in-11-2-what-is-wrong-with-this-quote/#comment-4559</link>
		<dc:creator><![CDATA[Charles Hooper]]></dc:creator>
		<pubDate>Sun, 18 Mar 2012 18:10:46 +0000</pubDate>
		<guid isPermaLink="false">http://hoopercharles.wordpress.com/?p=6098#comment-4559</guid>
		<description><![CDATA[Mich,

I believe that your statement is correct with a small adjustment:
&lt;blockquote&gt;
it would be easier to point out that the optimizer will not use an index range scan for a not equals &lt;i&gt;[unless hinted to use the index].&lt;/i&gt;
&lt;/blockquote&gt;
 
&lt;blockquote&gt;
So Optimizer can use an index fast full scan. That is read the index as if it were a table using multiblock IO, does not read it in sorted order, just reads the blocks as it hits them.
&lt;/blockquote&gt;
That statement agrees with my understanding.

&lt;blockquote&gt;
If we have above does Oracle do some prefetching of the blocks at all to speed up the procressing?
&lt;/blockquote&gt;
I am not sure that I understand this statement.  During an index fast full scan, the runtime engine will read multiple blocks at a time up to the number of blocks specified for the DB_FILE_MULTIBLOCK_READ_COUNT (the actual number of blocks read in a single read request could be smaller based on extent sizes and blocks that are already in the buffer cache).  As far as I am aware, this multi-block read is not considered &quot;prefetching&quot;, which seems to be more commonly associated with batching multiple block reads (for instance during an INDEX FULL SCAN) that would otherwise result in db file sequential reads into either db file scattered reads (logically adjacent blocks) or db file parallel reads (logically non-adjacent blocks) during an index range scan.  The number of logically non-adjacent blocks read using a db file parallel read is controlled by the _DB_FILE_NONCONTIG_MBLOCK_READ_COUNT hidden parameter, which seems to default to a value of 11 blocks in 11.2.0.2.  If I remember correctly, _DISABLE_INDEX_BLOCK_PREFETCHING may be set to TRUE to disable this optimization, and there may also be an Oracle EVENT that also disables the combining of multiple non-adjacent block reads into a single db file parallel read request.  See the following OTN thread for a discussion between Timur Akhmadeev and me regarding index prefetching:
https://forums.oracle.com/forums/thread.jspa?threadID=941864

Jonathan Lewis also nicely summarized prefetching on page 82 of this article:
http://jonathanlewis.files.wordpress.com/2008/07/ls2.pdf

We are able to see prefetching with this example (using the same table and index created at the start of this article):
&lt;pre&gt;
DROP TABLE T1 PURGE;
 
CREATE TABLE T1 AS
SELECT
  ROWNUM C1,
  DECODE(ROWNUM,1,1,0) C2,
  LPAD(&#039;A&#039;,255,&#039;A&#039;) C3
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=1000000;
 
CREATE UNIQUE INDEX IND_T1_C1 ON T1(C1);
CREATE INDEX IND_T1_C2 ON T1(C2);
 
ALTER TABLE T1 MODIFY (C1 NOT NULL, C2 NOT NULL);
 
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt;USER,TABNAME=&gt;&#039;T1&#039;,CASCADE=&gt;TRUE,ESTIMATE_PERCENT=&gt;100,METHOD_OPT=&gt;&#039;FOR ALL INDEXED COLUMNS SIZE 254&#039;)
 
ALTER SYSTEM FLUSH BUFFER_CACHE;
&lt;/pre&gt;

I will process the following query in the DBMS Xplan viewer in my Hyper-Extended Oracle Performance Monitor (http://hoopercharles.wordpress.com/2012/03/12/thoughts-on-a-hyper-extended-oracle-performance-monitor-beta/ ) with an enabled 10046 and 10053 trace:
&lt;pre&gt;
SELECT /*+ INDEX(T1 IND_T1_C1) */
  C1,
  C2,
  SUBSTR(C3,1,10) C3
FROM
  T1
WHERE
  C1 BETWEEN 1 AND 10000;
&lt;/pre&gt;

The execution plan output follows:
&lt;pre&gt;
SELECT /*+ INDEX(T1 IND_T1_C1) */
  C1,
  C2,
  SUBSTR(C3,1,10) C3
FROM
  T1
WHERE
  C1 BETWEEN 1 AND 10000;
 
SQL_ID  5fg6g9cyg1hht, child number 0
-------------------------------------
SELECT /*+ INDEX(T1 IND_T1_C1) */    C1,    C2,    SUBSTR(C3,1,10) C3  
FROM    T1  WHERE    C1 BETWEEN 1 AND 10000
 
Plan hash value: 683303157
 
------------------------------------------------------------------------------------------------------------
&#124; Id  &#124; Operation                   &#124; Name      &#124; Starts &#124; E-Rows &#124; A-Rows &#124;   A-Time   &#124; Buffers &#124; Reads  &#124;
------------------------------------------------------------------------------------------------------------
&#124;   0 &#124; SELECT STATEMENT            &#124;           &#124;      1 &#124;        &#124;  10000 &#124;00:00:00.06 &#124;     599 &#124;    448 &#124;
&#124;   1 &#124;  TABLE ACCESS BY INDEX ROWID&#124; T1        &#124;      1 &#124;   9998 &#124;  10000 &#124;00:00:00.06 &#124;     599 &#124;    448 &#124;
&#124;*  2 &#124;   INDEX RANGE SCAN          &#124; IND_T1_C1 &#124;      1 &#124;   9998 &#124;  10000 &#124;00:00:00.01 &#124;     122 &#124;     40 &#124;
------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
--------------------------------------------------- 
   2 - access(&quot;C1&quot;&gt;=1 AND &quot;C1&quot;&lt;=10000)
&lt;/pre&gt;

The 10046 portion of the trace file includes the following, which demonstrates prefetching of index and table blocks:
&lt;pre&gt;
PARSING IN CURSOR #424214864 len=114 dep=0 uid=64 oct=3 lid=64 tim=1009009341711 hv=1022411289 ad=&#039;3eb8c0770&#039; sqlid=&#039;5fg6g9cyg1hht&#039;
SELECT /*+ INDEX(T1 IND_T1_C1) */ 
  C1, 
  C2, 
  SUBSTR(C3,1,10) C3 
FROM 
  T1 
WHERE 
  C1 BETWEEN 1 AND 10000
END OF STMT
PARSE #424214864:c=31200,e=27003,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=683303157,tim=1009009341710
EXEC #424214864:c=0,e=36,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=683303157,tim=1009009341844
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 2 driver id=1413697536 #bytes=1 p3=0 obj#=523 tim=1009009341900
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 634 file#=8 block#=33056 blocks=8 obj#=103840 tim=1009009342618    --- index
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 639 file#=8 block#=68720 blocks=8 obj#=103840 tim=1009009343432    --- index
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 616 file#=7 block#=99176 blocks=8 obj#=103839 tim=1009009344176    --- table
FETCH #424214864:c=0,e=2442,p=24,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009344373
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 792 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009345209
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009345270
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 499 file#=8 block#=216 blocks=8 obj#=103839 tim=1009009345865
FETCH #424214864:c=0,e=770,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009346013
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 496 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009346539
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009346591
FETCH #424214864:c=0,e=212,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009346778
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 583 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009347388
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009347426
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 544 file#=7 block#=99184 blocks=8 obj#=103839 tim=1009009348050    --- table
FETCH #424214864:c=0,e=741,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009348155
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 545 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009348729
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009348785
FETCH #424214864:c=0,e=127,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009348898
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 484 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009349402
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009349453
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 520 file#=8 block#=224 blocks=8 obj#=103839 tim=1009009350076      --- table
FETCH #424214864:c=0,e=749,p=8,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009350179
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 515 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009350717
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009350761
FETCH #424214864:c=0,e=130,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009350878
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 484 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009351383
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009351438
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 481 file#=7 block#=99192 blocks=8 obj#=103839 tim=1009009352017    --- table
FETCH #424214864:c=0,e=761,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009352176
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 555 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009352760
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009352822
FETCH #424214864:c=0,e=188,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009352986
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 648 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009353661
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009353738
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 448 file#=8 block#=15816 blocks=8 obj#=103839 tim=1009009354243    --- table
FETCH #424214864:c=0,e=667,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009354389
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 583 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009354995
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009355052
FETCH #424214864:c=0,e=162,p=0,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009355189
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 519 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009355730
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009355799
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 620 file#=8 block#=15824 blocks=8 obj#=103839 tim=1009009356510    --- table
FETCH #424214864:c=0,e=990,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009356763
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 636 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009357433
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009357514
FETCH #424214864:c=0,e=233,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009357724
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 633 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009358392
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 507 file#=8 block#=15832 blocks=8 obj#=103839 tim=1009009359053    --- table
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009359096
FETCH #424214864:c=0,e=702,p=8,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009359217
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 617 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009359864
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009359910
FETCH #424214864:c=0,e=114,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009360008
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 551 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009360580
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009360640
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 522 file#=8 block#=15840 blocks=8 obj#=103839 tim=1009009361276    --- table
FETCH #424214864:c=0,e=819,p=8,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009361433
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 724 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009362181
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009362263
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 420 file#=8 block#=15848 blocks=8 obj#=103839 tim=1009009362900    --- table
FETCH #424214864:c=0,e=707,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009362946
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 510 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009363479
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009363529
FETCH #424214864:c=0,e=169,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009363671
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 548 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009364300
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009364357
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 487 file#=8 block#=15856 blocks=8 obj#=103839 tim=1009009364997    --- table
FETCH #424214864:c=0,e=708,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009365040
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 525 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009365591
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009365650
FETCH #424214864:c=0,e=207,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009365831
WAIT #424214864: nam=&#039;SQL*Net message from client&#039; ela= 506 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009366369
WAIT #424214864: nam=&#039;SQL*Net message to client&#039; ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009366423
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 330 file#=8 block#=33064 blocks=8 obj#=103840 tim=1009009366871    --- index
WAIT #424214864: nam=&#039;db file scattered read&#039; ela= 440 file#=8 block#=15864 blocks=8 obj#=103839 tim=1009009367425    --- table
&lt;/pre&gt;

I did not find the words &quot;index prefetching&quot;, or &quot;prefetch&quot; in the 10053 portion of the trace file, so I suspect that notation has been removed from recent versions of 10053 trace files.]]></description>
		<content:encoded><![CDATA[<p>Mich,</p>
<p>I believe that your statement is correct with a small adjustment:</p>
<blockquote><p>
it would be easier to point out that the optimizer will not use an index range scan for a not equals <i>[unless hinted to use the index].</i>
</p></blockquote>
<blockquote><p>
So Optimizer can use an index fast full scan. That is read the index as if it were a table using multiblock IO, does not read it in sorted order, just reads the blocks as it hits them.
</p></blockquote>
<p>That statement agrees with my understanding.</p>
<blockquote><p>
If we have above does Oracle do some prefetching of the blocks at all to speed up the procressing?
</p></blockquote>
<p>I am not sure that I understand this statement.  During an index fast full scan, the runtime engine will read multiple blocks at a time up to the number of blocks specified for the DB_FILE_MULTIBLOCK_READ_COUNT (the actual number of blocks read in a single read request could be smaller based on extent sizes and blocks that are already in the buffer cache).  As far as I am aware, this multi-block read is not considered &#8220;prefetching&#8221;, which seems to be more commonly associated with batching multiple block reads (for instance during an INDEX FULL SCAN) that would otherwise result in db file sequential reads into either db file scattered reads (logically adjacent blocks) or db file parallel reads (logically non-adjacent blocks) during an index range scan.  The number of logically non-adjacent blocks read using a db file parallel read is controlled by the _DB_FILE_NONCONTIG_MBLOCK_READ_COUNT hidden parameter, which seems to default to a value of 11 blocks in 11.2.0.2.  If I remember correctly, _DISABLE_INDEX_BLOCK_PREFETCHING may be set to TRUE to disable this optimization, and there may also be an Oracle EVENT that also disables the combining of multiple non-adjacent block reads into a single db file parallel read request.  See the following OTN thread for a discussion between Timur Akhmadeev and me regarding index prefetching:<br />
<a href="https://forums.oracle.com/forums/thread.jspa?threadID=941864" rel="nofollow">https://forums.oracle.com/forums/thread.jspa?threadID=941864</a></p>
<p>Jonathan Lewis also nicely summarized prefetching on page 82 of this article:<br />
<a href="http://jonathanlewis.files.wordpress.com/2008/07/ls2.pdf" rel="nofollow">http://jonathanlewis.files.wordpress.com/2008/07/ls2.pdf</a></p>
<p>We are able to see prefetching with this example (using the same table and index created at the start of this article):</p>
<pre>
DROP TABLE T1 PURGE;
 
CREATE TABLE T1 AS
SELECT
  ROWNUM C1,
  DECODE(ROWNUM,1,1,0) C2,
  LPAD('A',255,'A') C3
FROM
  DUAL
CONNECT BY
  LEVEL&lt;=1000000;
 
CREATE UNIQUE INDEX IND_T1_C1 ON T1(C1);
CREATE INDEX IND_T1_C2 ON T1(C2);
 
ALTER TABLE T1 MODIFY (C1 NOT NULL, C2 NOT NULL);
 
EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt;USER,TABNAME=&gt;'T1',CASCADE=&gt;TRUE,ESTIMATE_PERCENT=&gt;100,METHOD_OPT=&gt;'FOR ALL INDEXED COLUMNS SIZE 254')
 
ALTER SYSTEM FLUSH BUFFER_CACHE;
</pre>
<p>I will process the following query in the DBMS Xplan viewer in my Hyper-Extended Oracle Performance Monitor (<a href="http://hoopercharles.wordpress.com/2012/03/12/thoughts-on-a-hyper-extended-oracle-performance-monitor-beta/" rel="nofollow">http://hoopercharles.wordpress.com/2012/03/12/thoughts-on-a-hyper-extended-oracle-performance-monitor-beta/</a> ) with an enabled 10046 and 10053 trace:</p>
<pre>
SELECT /*+ INDEX(T1 IND_T1_C1) */
  C1,
  C2,
  SUBSTR(C3,1,10) C3
FROM
  T1
WHERE
  C1 BETWEEN 1 AND 10000;
</pre>
<p>The execution plan output follows:</p>
<pre>
SELECT /*+ INDEX(T1 IND_T1_C1) */
  C1,
  C2,
  SUBSTR(C3,1,10) C3
FROM
  T1
WHERE
  C1 BETWEEN 1 AND 10000;
 
SQL_ID  5fg6g9cyg1hht, child number 0
-------------------------------------
SELECT /*+ INDEX(T1 IND_T1_C1) */    C1,    C2,    SUBSTR(C3,1,10) C3  
FROM    T1  WHERE    C1 BETWEEN 1 AND 10000
 
Plan hash value: 683303157
 
------------------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name      | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |           |      1 |        |  10000 |00:00:00.06 |     599 |    448 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T1        |      1 |   9998 |  10000 |00:00:00.06 |     599 |    448 |
|*  2 |   INDEX RANGE SCAN          | IND_T1_C1 |      1 |   9998 |  10000 |00:00:00.01 |     122 |     40 |
------------------------------------------------------------------------------------------------------------
 
Predicate Information (identified by operation id):
--------------------------------------------------- 
   2 - access("C1"&gt;=1 AND "C1"&lt;=10000)
</pre>
<p>The 10046 portion of the trace file includes the following, which demonstrates prefetching of index and table blocks:</p>
<pre>
PARSING IN CURSOR #424214864 len=114 dep=0 uid=64 oct=3 lid=64 tim=1009009341711 hv=1022411289 ad='3eb8c0770' sqlid='5fg6g9cyg1hht'
SELECT /*+ INDEX(T1 IND_T1_C1) */ 
  C1, 
  C2, 
  SUBSTR(C3,1,10) C3 
FROM 
  T1 
WHERE 
  C1 BETWEEN 1 AND 10000
END OF STMT
PARSE #424214864:c=31200,e=27003,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=1,plh=683303157,tim=1009009341710
EXEC #424214864:c=0,e=36,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,plh=683303157,tim=1009009341844
WAIT #424214864: nam='SQL*Net message to client' ela= 2 driver id=1413697536 #bytes=1 p3=0 obj#=523 tim=1009009341900
WAIT #424214864: nam='db file scattered read' ela= 634 file#=8 block#=33056 blocks=8 obj#=103840 tim=1009009342618    --- index
WAIT #424214864: nam='db file scattered read' ela= 639 file#=8 block#=68720 blocks=8 obj#=103840 tim=1009009343432    --- index
WAIT #424214864: nam='db file scattered read' ela= 616 file#=7 block#=99176 blocks=8 obj#=103839 tim=1009009344176    --- table
FETCH #424214864:c=0,e=2442,p=24,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009344373
WAIT #424214864: nam='SQL*Net message from client' ela= 792 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009345209
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009345270
WAIT #424214864: nam='db file scattered read' ela= 499 file#=8 block#=216 blocks=8 obj#=103839 tim=1009009345865
FETCH #424214864:c=0,e=770,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009346013
WAIT #424214864: nam='SQL*Net message from client' ela= 496 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009346539
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009346591
FETCH #424214864:c=0,e=212,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009346778
WAIT #424214864: nam='SQL*Net message from client' ela= 583 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009347388
WAIT #424214864: nam='SQL*Net message to client' ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009347426
WAIT #424214864: nam='db file scattered read' ela= 544 file#=7 block#=99184 blocks=8 obj#=103839 tim=1009009348050    --- table
FETCH #424214864:c=0,e=741,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009348155
WAIT #424214864: nam='SQL*Net message from client' ela= 545 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009348729
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009348785
FETCH #424214864:c=0,e=127,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009348898
WAIT #424214864: nam='SQL*Net message from client' ela= 484 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009349402
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009349453
WAIT #424214864: nam='db file scattered read' ela= 520 file#=8 block#=224 blocks=8 obj#=103839 tim=1009009350076      --- table
FETCH #424214864:c=0,e=749,p=8,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009350179
WAIT #424214864: nam='SQL*Net message from client' ela= 515 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009350717
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009350761
FETCH #424214864:c=0,e=130,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009350878
WAIT #424214864: nam='SQL*Net message from client' ela= 484 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009351383
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009351438
WAIT #424214864: nam='db file scattered read' ela= 481 file#=7 block#=99192 blocks=8 obj#=103839 tim=1009009352017    --- table
FETCH #424214864:c=0,e=761,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009352176
WAIT #424214864: nam='SQL*Net message from client' ela= 555 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009352760
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009352822
FETCH #424214864:c=0,e=188,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009352986
WAIT #424214864: nam='SQL*Net message from client' ela= 648 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009353661
WAIT #424214864: nam='SQL*Net message to client' ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009353738
WAIT #424214864: nam='db file scattered read' ela= 448 file#=8 block#=15816 blocks=8 obj#=103839 tim=1009009354243    --- table
FETCH #424214864:c=0,e=667,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009354389
WAIT #424214864: nam='SQL*Net message from client' ela= 583 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009354995
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009355052
FETCH #424214864:c=0,e=162,p=0,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009355189
WAIT #424214864: nam='SQL*Net message from client' ela= 519 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009355730
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009355799
WAIT #424214864: nam='db file scattered read' ela= 620 file#=8 block#=15824 blocks=8 obj#=103839 tim=1009009356510    --- table
FETCH #424214864:c=0,e=990,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009356763
WAIT #424214864: nam='SQL*Net message from client' ela= 636 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009357433
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009357514
FETCH #424214864:c=0,e=233,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009357724
WAIT #424214864: nam='SQL*Net message from client' ela= 633 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009358392
WAIT #424214864: nam='db file scattered read' ela= 507 file#=8 block#=15832 blocks=8 obj#=103839 tim=1009009359053    --- table
WAIT #424214864: nam='SQL*Net message to client' ela= 0 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009359096
FETCH #424214864:c=0,e=702,p=8,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009359217
WAIT #424214864: nam='SQL*Net message from client' ela= 617 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009359864
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009359910
FETCH #424214864:c=0,e=114,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009360008
WAIT #424214864: nam='SQL*Net message from client' ela= 551 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009360580
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009360640
WAIT #424214864: nam='db file scattered read' ela= 522 file#=8 block#=15840 blocks=8 obj#=103839 tim=1009009361276    --- table
FETCH #424214864:c=0,e=819,p=8,cr=7,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009361433
WAIT #424214864: nam='SQL*Net message from client' ela= 724 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009362181
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009362263
WAIT #424214864: nam='db file scattered read' ela= 420 file#=8 block#=15848 blocks=8 obj#=103839 tim=1009009362900    --- table
FETCH #424214864:c=0,e=707,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009362946
WAIT #424214864: nam='SQL*Net message from client' ela= 510 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009363479
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009363529
FETCH #424214864:c=0,e=169,p=0,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009363671
WAIT #424214864: nam='SQL*Net message from client' ela= 548 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009364300
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009364357
WAIT #424214864: nam='db file scattered read' ela= 487 file#=8 block#=15856 blocks=8 obj#=103839 tim=1009009364997    --- table
FETCH #424214864:c=0,e=708,p=8,cr=6,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009365040
WAIT #424214864: nam='SQL*Net message from client' ela= 525 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009365591
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009365650
FETCH #424214864:c=0,e=207,p=0,cr=5,cu=0,mis=0,r=100,dep=0,og=1,plh=683303157,tim=1009009365831
WAIT #424214864: nam='SQL*Net message from client' ela= 506 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009366369
WAIT #424214864: nam='SQL*Net message to client' ela= 1 driver id=1413697536 #bytes=1 p3=0 obj#=103839 tim=1009009366423
WAIT #424214864: nam='db file scattered read' ela= 330 file#=8 block#=33064 blocks=8 obj#=103840 tim=1009009366871    --- index
WAIT #424214864: nam='db file scattered read' ela= 440 file#=8 block#=15864 blocks=8 obj#=103839 tim=1009009367425    --- table
</pre>
<p>I did not find the words &#8220;index prefetching&#8221;, or &#8220;prefetch&#8221; in the 10053 portion of the trace file, so I suspect that notation has been removed from recent versions of 10053 trace files.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
