<?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>IN ORACLE MILIEU ...</title>
	<atom:link href="http://avdeo.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://avdeo.com</link>
	<description>Beyond Knowledge</description>
	<lastBuildDate>Thu, 02 Feb 2012 12:03:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='avdeo.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>IN ORACLE MILIEU ...</title>
		<link>http://avdeo.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://avdeo.com/osd.xml" title="IN ORACLE MILIEU ..." />
	<atom:link rel='hub' href='http://avdeo.com/?pushpress=hub'/>
		<item>
		<title>Inside Index block &#8211; Oracle Database 11g</title>
		<link>http://avdeo.com/2011/12/12/inside-index-block-oracle-database-11g/</link>
		<comments>http://avdeo.com/2011/12/12/inside-index-block-oracle-database-11g/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 19:38:26 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[block internals]]></category>
		<category><![CDATA[block numbers]]></category>
		<category><![CDATA[index block]]></category>
		<category><![CDATA[inside blocks]]></category>
		<category><![CDATA[tsn]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=887</guid>
		<description><![CDATA[I ran into a scenario where I really wanted to check whats inside the leaf block of an index. This post is to dig inside the index leaf block and find out various facts stored inside a block. We will start with taking a dump of a block SYS.ORCL&#62;alter session set tracefile_identifier='INDEX_BLOCK_DUMP'; Session altered. SYS.ORCL&#62;alter [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=887&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>I ran into a scenario where I really wanted to check whats inside the leaf block of an index.</p>
<p>This post is to dig inside the index leaf block and find out various facts stored inside a block.</p>
<p>We will start with taking a dump of a block</p>
<pre>SYS.ORCL&gt;alter session set tracefile_identifier='INDEX_BLOCK_DUMP';
Session altered.
SYS.ORCL&gt;alter system dump datafile 292 block 245790;
System altered.
SYS.ORCL&gt;</pre>
<p>You will get a trace file having name something like &#8220;<strong>&lt;DB_NAME&gt;_ora_&lt;PID&gt;_INDEX_BLOCK_DUMP.tr</strong>c&#8221; in your trace directory</p>
<p>Even if you dont use tracefile_identifier, you can still see the name of the dump file using following query</p>
<pre>SYS.ORCL&gt;select value from v$diag_info where name = 'Default Trace File';
VALUE
-----------------------------------------------------------------
/dumps-01/diag/rdbms/orcl_b/orcl/trace/orcl_ora_11416.trc
1 row selected.
SYS.ORCL&gt;</pre>
<p>At the start of the block you will see following details</p>
<pre>*********************************************************************
Start dump data blocks tsn: 17 file#:292 minblk 245790 maxblk 245790
Block dump from cache:
Dump of buffer cache at level 4 for tsn=17, rdba=1224982558
Block dump from disk:
buffer tsn: 17 rdba: 0x4903c01e (292/245790)
scn: 0x06ca.4d4684c7 seq: 0x01 flg: 0x04 tail: 0x84c70601
frmt: 0x02 chkval: 0xe178 type: 0x06=trans data
*********************************************************************</pre>
<p><strong>tsn &#8211;&gt;</strong> Tablespace Number = 17<br />
<strong>file# &#8211;&gt;</strong> File # = 292<br />
<strong>minblk &amp; maxblk &#8211;&gt;</strong> Min block and Max block numbers = 245790<br />
<strong>rdba &#8211;&gt;</strong> Relative data block address. Its value is 0x4903c01e in hexa decimal and 1224982558 in decimal.<br />
We can get rdba using dbms_utility.make_data_block_address</p>
<pre>SYS.ORCL&gt;select dbms_utility.make_data_block_address(292,245790) from dual;
DBMS_UTILITY.MAKE_DATA_BLOCK_ADDRESS(292,245790)
------------------------------------------------
 1224982558</pre>
<p>After above lines we have dump of memory. You will see a line something as below</p>
<p>Dump of memory from 0x00002B5C26C2DA00 to 0x00002B5C26C2FA00</p>
<p>So at each address it will print the content. Its very difficult to read this format.</p>
<pre>2B5C26C2DA00 0000A206 4903C01E 4D4684C7 040106CA [.......I..FM....]
2B5C26C2DA10 0000E178 00000002 000551A1 4CFB5368 [x........Q..hS.L]
2B5C26C2DA20 000006CA 0032001D 4903C009 000F0046 [......2....IF...]
2B5C26C2DA30 00221BD6 01460CC8 0001F2FC 06CAC000 [.."...F.........]
2B5C26C2DA40 40FE45EE 001D00EE 0008E5F9 0086EC85 [.E.@............]
2B5C26C2DA50 003EC8BA 06CA8000 40FA9BFF 00000000 [..&gt;........@....]
2B5C26C2DA60 00000000 00000000 00000000 00000000 [................]
2B5C26C2DA70 00000000 00100040 0027C6F8 0085DF28 [....@.....'.(...]</pre>
<p>But once this memory dump is complete, we can see some readable information stored in index block. Here is what comes next</p>
<pre>seg/obj: 0x551a1 csc: 0x6ca.4cfb5368 itc: 29 flg: E typ: 2 - INDEX
 brn: 0 bdba: 0x4903c009 ver: 0x01 opc: 0
 inc: 0 exflg: 0</pre>
<p><strong>seg/obj</strong> is the object_id. 0x551a1 = 348577 in 348577 in decimal.</p>
<pre>SYS.ORCL&gt;select object_name from dba_objects where data_object_id = 348577;
OBJECT_NAME
-------------------------
UNIQ_FPM_MSG_WHSE_CAT_ID
1 row selected.</pre>
<p>This is the index for which we dumped the block.</p>
<p><strong>csc: 0x6ca.4cfb5368 &#8211;&gt;</strong> This is the comit SCN number of the block<br />
<strong>itc: 29 &#8211;&gt;</strong> Number of interested transaction list(ITL) entry in the block.<br />
<strong>typ: 2 &#8211; INDEX &#8211;&gt;</strong> Indicates this is an index block</p>
<p>Next comes the Interested Transaction List(ITL) entries. We had 29 ITL entries as indicated above by itc: 29</p>
<pre>Itl  Xid                 Uba                Flag Lck   Scn/Fsc
0x01 0x0046.00f.00221bd6 0x01460cc8.f2fc.01 CB-- 0 scn 0x06ca.40fe45ee
0x02 0x00ee.01d.0008e5f9 0x0086ec85.c8ba.3e C--- 0 scn 0x06ca.40fa9bff
0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x04 0x0040.010.0027c6f8 0x0085df28.cb0f.0b C--- 0 scn 0x06ca.40fb14e2
0x05 0x00f0.017.00090d20 0x37860557.c767.36 C--- 0 scn 0x06ca.40fb15a7
0x06 0x013d.020.0002205c 0x3802952d.202e.26 C--- 0 scn 0x06ca.40fd6d83
0x07 0x001d.012.0049340a 0x38063ebe.c0d6.48 C--- 0 scn 0x06ca.40fd6e3e
0x08 0x00b5.018.000e6ee9 0x384279bf.95f1.07 C--- 0 scn 0x06ca.40fe4336
0x09 0x010e.007.000a4514 0x0088535e.b343.19 C--- 0 scn 0x06ca.40fa9b08
0x0a 0x00df.00f.0009db56 0x014571c8.e27e.0a C--- 0 scn 0x06ca.40fe446d
0x0b 0x00f4.00b.00092665 0x37c65073.c520.27 C--- 0 scn 0x06ca.4100f955
0x0c 0x0129.017.00035f0e 0x0187980c.2a1a.04 C--- 0 scn 0x06ca.4100fa77
0x0d 0x007a.002.0010db5b 0x38458cb5.5bbd.20 C--- 0 scn 0x06ca.41168fad
0x0e 0x0069.00e.0017dd7d 0x3807b2e2.1390.30 C--- 0 scn 0x06ca.411691b0
0x0f 0x00d7.006.0009a7ee 0x38417fbc.dd00.19 C--- 0 scn 0x06ca.41169313
0x10 0x0181.003.000170b0 0x00c78696.190d.2b C--- 0 scn 0x06ca.41169bc6
0x11 0x00bd.014.000d2ddf 0x3805ab0d.72f9.19 C--- 0 scn 0x06ca.41169ecc
0x12 0x0001.019.00634f4c 0x3802e302.4fd4.0d C--- 0 scn 0x06ca.4116ab9e
0x13 0x0035.014.003a9a1d 0x014691a5.cda1.3d C--- 0 scn 0x06ca.4116ad76
0x14 0x017a.017.00018a03 0x37c4d213.17c4.0d C--- 0 scn 0x06ca.4116b388
0x15 0x006a.012.0017f16a 0x37878e97.329f.2b C--- 0 scn 0x06ca.4165b46c
0x16 0x00f0.01b.00090d4e 0x3846d24e.c76b.36 C--- 0 scn 0x06ca.4165b57c
0x17 0x0168.004.00019960 0x00c77875.18ab.08 C--- 0 scn 0x06ca.4165b7a5
0x18 0x0104.002.0006b6fd 0x38401fbe.a734.0e C--- 0 scn 0x06ca.4165b951
0x19 0x0044.018.00275fa5 0x38417b7e.cf86.3c C--- 0 scn 0x06ca.41035e03
0x1a 0x0127.01c.0006d44b 0x008602ca.5584.04 C--- 0 scn 0x06ca.40f95f82
0x1b 0x00ba.004.000dbc9a 0x3786425e.74f4.32 C--- 0 scn 0x06ca.40f96071
0x1c 0x0194.004.00014665 0x38464daf.1aca.46 C--- 0 scn 0x06ca.40f9c995
0x1d 0x0014.00c.0066b5d6 0x01865ee3.e323.08 C--- 0 scn 0x06ca.40f9ca31</pre>
<p><strong>Itl &#8211;&gt;</strong> Slot Id of interested transaction<br />
<strong>Xid &#8211;&gt;</strong> Transaction ID od transaction occupying that ITL<br />
<strong>Uba &#8211;&gt;</strong> Undo block address<br />
<strong>Flag &#8211;&gt;</strong> State for current transaction (C &#8211; Commited)<br />
<strong>Lck &#8211;&gt;</strong> Number of Lock held by the transacion<br />
<strong>Scn/Fsc &#8211;&gt;</strong> SCN number of the current transaction</p>
<p>Once ITL list is displayed, next comes the leaf block dump.<br />
At the start of leaf block dump it gives the header information of the block</p>
<pre>Leaf block dump
===============
header address 47674787290348=0x2b5c26c2dcec     =&gt; Header start and end address
kdxcolev 0                                       =&gt; Index Level. 0 represent leaf block
KDXCOLEV Flags = - - -
kdxcolok 0                                       =&gt; Indicates that no block transaction happening right now
kdxcoopc 0x80: opcode=0: iot flags=--- is converted=Y    =&gt; Internal Operation code
kdxconco 3                                        =&gt; Index Column Count
kdxcosdc 8                                        =&gt; Count of index structural changes involving block
kdxconro 48                                       =&gt; Number of index records in this block
kdxcofbo 132=0x84                                 =&gt; Offset from start to the beginning of free space
kdxcofeo 1435=0x59b                               =&gt; Offset to end of free space (ie. first portion of block containing index data)
kdxcoavs 1303                                     =&gt; Available space in the block (effective space between kdxcofbo and kdxcofeo)
kdxlespl 0                                        =&gt; Bytes of uncommited data at the time of block split that have been cleaned out
kdxlende 0                                        =&gt; Number of deleted entries
kdxlenxt 830726637=0x3183e1ed                     =&gt; Pointer to next leaf block
kdxleprv 830721132=0x3183cc6c                     =&gt; Pointer to previous leaf block
kdxledsz 10                                       =&gt; Deleted space
kdxlebksz 7384                                    =&gt; Size of usable block space</pre>
<p>After header, comes the index information as shown below</p>
<pre>row#0[3602] flag: ------, lock: 0, len=61, data:(10): 00 0c 13 af 37 47 af ee 00 05
col 0; len 26; (26):
 35 35 39 32 35 38 5f 31 33 35 33 32 35 30 31 34 33 5f 36 38 5e 32 34 31 34
 30
col 1; len 4; (4): 4c 45 4a 31
col 2; len 16; (16): 43 68 61 6e 67 65 50 69 63 6b 53 74 61 74 75 73
row#1[3663] flag: ------, lock: 0, len=57, data:(10): 00 0c 13 af 37 47 af 24 00 42
col 0; len 26; (26):
 35 35 39 22 35 38 5f 31 33 32 33 32 35 30 32 32 33 5f 36 38 5f 32 34 31 34
 30
col 1; len 4; (4): 4c 45 4f 33
col 2; len 12; (12): 50 69 63 6b 43 6f 6d 70 6c 65 74 65</pre>
<p>Here is what above values mean</p>
<p><strong>row#0 -&gt;</strong> First row in the block. Row starts from 0<br />
<strong>[3602] -&gt;</strong> Starting location within the block<br />
<strong>flag: -&gt;</strong> Flag to give information above the record in index leaf block. If you delete a row, the flag will be marked D, meaning deleted.<br />
<strong>lock -&gt;</strong> Lock information at row level<br />
<strong>len -&gt;</strong> Total length of a index record<br />
<strong>data -&gt;</strong> I guess this should be the length of rowid which is following this &#8220;00 0c 13 af 37 47 af ee 00 05&#8243;</p>
<p>Each row in this index has 3 columns. Columns start with col0. So we have column information in col0, col1 and col2</p>
<p><strong>col0 -&gt;</strong> First column<br />
<strong>len -&gt;</strong> Length of the column. 26 in this case.<br />
Value after that is the actual value in base 16 stored in the block.</p>
<p>We can actually get real value for the values stored above using following function SQL.<br />
You need to pass the hex value seen in block dump to a function <strong>dbms_stats.convert_raw_value</strong> and it returns the required values.</p>
<p>Lets say we want to find out the value for first row (Value for each column in first row)</p>
<pre>SQL&gt;var col1 varchar2(1000);
SQL&gt;exec dbms_stats.convert_raw_value(replace('35 35 39 32 35 38 5f 31 33 32 33 32 35 30 30 32 33 5f 36 38 5f 32 34 31 34 30',' ',''),:col1);
PL/SQL procedure successfully completed.
SQL&gt;var col2 varchar2(10);
SQL&gt;exec dbms_stats.convert_raw_value(replace('4c 45 4a 31',' ',''),:col2);
PL/SQL procedure successfully completed.
SQL&gt;var col3 varchar2(100);
SQL&gt;exec dbms_stats.convert_raw_value(replace('43 68 61 6e 67 65 50 69 63 6b 53 74 61 74 75 73',' ',''),:col3);
PL/SQL procedure successfully completed.
COL1
-----------------------------
559258_1323250023_68_24140

COL2
-----------------------------
ABC

COL3
-----------------------------
EmployeeStatus
SQL&gt;</pre>
<p>Similarly you can write your own PLSQL code and find out all the values stored inside an index block.</p>
<p>Hope this helps !!</p>
<br />Filed under: <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a> Tagged: <a href='http://avdeo.com/tag/block-internals/'>block internals</a>, <a href='http://avdeo.com/tag/block-numbers/'>block numbers</a>, <a href='http://avdeo.com/tag/index-block/'>index block</a>, <a href='http://avdeo.com/tag/inside-blocks/'>inside blocks</a>, <a href='http://avdeo.com/tag/tsn/'>tsn</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/887/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/887/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/887/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/887/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/887/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/887/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/887/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/887/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=887&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/12/12/inside-index-block-oracle-database-11g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle SQL Plan Management – Part 3</title>
		<link>http://avdeo.com/2011/08/07/oracle-sql-plan-management-%e2%80%93-part-3/</link>
		<comments>http://avdeo.com/2011/08/07/oracle-sql-plan-management-%e2%80%93-part-3/#comments</comments>
		<pubDate>Sun, 07 Aug 2011 12:51:46 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[baseline]]></category>
		<category><![CDATA[dba_sql_plan_baselines]]></category>
		<category><![CDATA[spm]]></category>
		<category><![CDATA[sql plan baseline]]></category>
		<category><![CDATA[sql plan management]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=882</guid>
		<description><![CDATA[SQL Plan Management – Oracle Database 11g You have seen the first 2 parts of SQL plan baselines Part 1 &#8211; http://avdeo.com/2011/06/02/oracle-sql-plan-management-part-1/ Part 2 &#8211; http://avdeo.com/2011/06/07/oracle-sql-plan-management-%e2%80%93-part-2/ In part 1 we have seen information about SPM and how to automatically capture the baseline In part 2 we have seen how to manually capture the baseline and [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=882&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1><span style="color:#000080;"><strong><strong>SQL Plan Management – Oracle Database 11g</strong></strong></span></h1>
<p>You have seen the first 2 parts of SQL plan baselines</p>
<p>Part 1 &#8211; http://avdeo.com/2011/06/02/oracle-sql-plan-management-part-1/<br />
Part 2 &#8211; http://avdeo.com/2011/06/07/oracle-sql-plan-management-%e2%80%93-part-2/</p>
<p>In part 1 we have seen information about SPM and how to automatically capture the baseline<br />
In part 2 we have seen how to manually capture the baseline and the affect of using FIXED variable<br />
In part 3 we will now see, how to import the baselines for SQL from some remote database and also how to set a specific plan for a query using hint and then creating baseline for that</p>
<h1><span style="color:#000080;">Importing baseline from remote database to our database</span></h1>
<p>Lets say we have a database and a table T in the database.</p>
<pre>SQL&gt; desc T
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 COL1                                               NUMBER
 COL2                                               VARCHAR2(50)
 COL3                                               DATE</pre>
<p>No Index exists on this table.</p>
<pre>SQL&gt; select count(1) from T;

  COUNT(1)
----------
   2097156

SQL&gt; select col1, count(1) from T group by col1;

      COL1   COUNT(1)
---------- ----------
         1          1
         2          3
         3    2097152

SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  1048K|    11M|  1424   (6)| 00:00:18 |
|*  1 |  TABLE ACCESS FULL| T    |  1048K|    11M|  1424   (6)| 00:00:18 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

13 rows selected.

SQL&gt;</pre>
<p>Lets create a baseline for this query manually.</p>
<p>Find the SQL ID using</p>
<pre>SQL&gt;select sql_id from v$sql where sql_text = 'select * from T where col1 = 1';

SQL_ID
-------------
5pvxxjg6n7mrp

SQL&gt;

DECLARE
  l_plans_loaded  PLS_INTEGER;
BEGIN
  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
    sql_id =&gt; '5pvxxjg6n7mrp');
END;
/

SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where signature IN (SELECT exact_matching_signature FROM v$sql WHERE sql_id='&amp;SQL_ID');
Enter value for sql_id: 5pvxxjg6n7mrp
old   1: select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where signature IN (SELECT exact_matching_signature FROM v$sql WHERE sql_id='&amp;SQL_ID')
new   1: select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where signature IN (SELECT exact_matching_signature FROM v$sql WHERE sql_id='5pvxxjg6n7mrp')

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO

SQL&gt;</pre>
<p>So now the baseline is created for this SQL.</p>
<p>If we check the plan it will show us Full Table Scan.</p>
<p>Now lets create an index.</p>
<pre>SQL&gt; create index T_IDX on T(col1);

Index created.

SQL&gt; exec DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=&gt; '&amp;owner', TABNAME =&gt; '&amp;tabname', DEGREE =&gt; 6, GRANULARITY =&gt; 'ALL' ,CASCADE =&gt; TRUE , METHOD_OPT =&gt; 'FOR ALL INDEXED COLUMNS SIZE 254');
Enter value for owner: ADVAITD_DBA
Enter value for tabname: T

PL/SQL procedure successfully completed.

SQL&gt;</pre>
<p>lets see the plan for same query again. Since we have created an index on col1 of table T, when using value 1 we expect an index to be used rather than FTS.</p>
<pre>SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |  1048K|    11M|  1424   (6)| 00:00:18 |
|*  1 |  TABLE ACCESS FULL| T    |  1048K|    11M|  1424   (6)| 00:00:18 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920f94ecae5c" used for this statement

17 rows selected.

SQL&gt;</pre>
<p>Here we clearly see baseline is getting used and it still uses FTS. This is a plan stability feature in 11g. No matter what changes we do, if a baseline already exists for a query and even if you create an index, it wont use that index unless you create a new baseline for that. As you know by now, new baseline will get created automatically only if you set OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES parameters is set to true. If this is set to false you have to create baseline manaully using DBMS_SPM package as shown above.</p>
<p>At this point of time we have an option to create a baseline and using DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE</p>
<p>But instead of using that we will try to export and import a baseline from some other DB having same query and tables.</p>
<p>So lets say, I have another database having same table and running same query. But that query is using correct index on col1. So we will see how to get that baseline exported and imported to our DB.<br />
In real time situation, we will get several cases where in same set of queries are running good in some other databases but thay are having bad plan in our databaes. So instead of trying to get the plan right using traditional methods, we can simply export and import the baseline of that query from some other DB where its performing better and plans will be fixed in our DB without much effort.<br />
So on my new DB, I have a correct plan as indicated below</p>
<pre>SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  2359K|   139M|   307   (1)| 00:00:04 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  2359K|   139M|   307   (1)| 00:00:04 |
|*  2 |   INDEX RANGE SCAN          | T_IDX |  2379K|       |    47   (3)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920fae82cf72" used for this statement

18 rows selected.

SQL&gt;</pre>
<p>Above query is using the baseline SYS_SQL_PLAN_1d83920fae82cf72</p>
<p>We will export and import this baseline in our database now. Following steps needs to be done to export and import the baseline</p>
<p><strong>1) Create a staging table</strong></p>
<pre>exec DBMS_SPM.CREATE_STGTAB_BASELINE('STGTAB', 'ADVAITD_DBA');</pre>
<p>STGTAB &#8211;&gt; Name of staging table. You can give any name which is not used till now. A table with this name will get created.<br />
ADVAITD_DBA &#8211;&gt; Owner of the table. Table will get created in this schema.</p>
<p><strong>2) Pack baseline into this table</strong></p>
<pre>declare
x number;
begin
x := DBMS_SPM.PACK_STGTAB_BASELINE('STGTAB', 'ADVAITD_DBA', sql_handle =&gt; 'SYS_SQL_1447ba3a1d83920f', plan_name =&gt; 'SYS_SQL_PLAN_1d83920fae82cf72' );
end;
/</pre>
<p><strong>3) Export the staging table from source DB where you have baseline packed</strong><br />
<strong>exp userid=advaitd_dba@new_db tables=&#8217;STGTAB&#8217; file=STGTAB.dmp log=STGTAB.log</strong></p>
<pre>advaitd.desktop$ exp userid=advaitd_dba@new_db tables='STGTAB' file=STGTAB.dmp log=STGTAB.log

Export: Release 10.2.0.2.0 - Production on Sun Aug 7 06:15:39 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Password:

Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options
Export done in US7ASCII character set and AL16UTF16 NCHAR character set
server uses UTF8 character set (possible charset conversion)

About to export specified tables via Conventional Path ...
. . exporting table                         STGTAB          1 rows exported
Export terminated successfully without warnings.
advaitd.desktop$</pre>
<p><strong>4) Import the table into the DB where you want to put the baseline</strong><br />
<strong>imp userid=advaitd_dba@our_db file=STGTAB.dmp log=STGTAB.log full=y</strong></p>
<pre>advaitd.desktop$ imp userid=advaitd_dba@our_db file=STGTAB.dmp log=STGTAB.log full=y

Import: Release 10.2.0.2.0 - Production on Sun Aug 7 06:20:54 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.

Password:

Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.7.0 - 64bit Production
With the Partitioning, Oracle Label Security, OLAP, Data Mining
and Real Application Testing options

Export file created by EXPORT:V10.02.01 via conventional path
import done in US7ASCII character set and AL16UTF16 NCHAR character set
import server uses UTF8 character set (possible charset conversion)
. importing ADVAITD_DBA's objects into ADVAITD_DBA
. importing ADVAITD_DBA's objects into ADVAITD_DBA
. . importing table                       "STGTAB"          1 rows imported
Import terminated successfully without warnings.
advaitd.desktop$</pre>
<p><strong>5) Unpack the staging table</strong></p>
<pre>declare
x number;
begin
x := DBMS_SPM.UNPACK_STGTAB_BASELINE('STGTAB', 'ADVAITD_DBA');
end;
/</pre>
<p>Now we can see 2 baseline.<br />
- One baseline which was already exisitng and doing FTS<br />
- One we imported just now which is using index</p>
<pre>SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where signature IN (SELECT exact_matching_signature FROM v$sql WHERE sql_id='&amp;SQL_ID');
Enter value for sql_id: 5pvxxjg6n7mrp
old   1: select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where signature IN (SELECT exact_matching_signature FROM v$sql WHERE sql_id='&amp;SQL_ID')
new   1: select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines where signature IN (SELECT exact_matching_signature FROM v$sql WHERE sql_id='5pvxxjg6n7mrp')

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  YES YES NO</pre>
<p>Now, if we check the plan for same query, we should be able to see index getting used and it will use the plan SYS_SQL_PLAN_1d83920fae82cf72 which we imported from other DB</p>
<pre>SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  1048K|    11M|    46   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  1048K|    11M|    46   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IDX |  1048K|       |    21   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920fae82cf72" used for this statement

18 rows selected.

SQL&gt;</pre>
<h1><span style="color:#000080;">Creating baseline for user created plans</span></h1>
<p>Lets go back to original situation where query on the table is doing a FTS. At this point instead of getting a profile from some other DB, lets create a correct profile using hints.</p>
<p>I am flushing the shared_pool so as to remove any exising plans from shared_pool</p>
<pre>SQL&gt; alter system flush shared_pool;

System altered.

SQL&gt; /

System altered.

SQL&gt;</pre>
<p>Lets use Index hint here and see if the query uses index.</p>
<pre>SQL&gt; select /*+ index(T_IDX T) +*/ * from T where col1 = 1;

      COL1 COL2                                               COL3
---------- -------------------------------------------------- -----------
         1                                                    10-JUL-2011

SQL&gt; explain plan for
  2  select /*+ index(T_IDX T) +*/ * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  1048K|    11M|   465   (2)| 00:00:06 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  1048K|    11M|   465   (2)| 00:00:06 |
|*  2 |   INDEX RANGE SCAN          | T_IDX |  1048K|       |   209   (2)| 00:00:03 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

14 rows selected.

SQL&gt;</pre>
<p>So using a hint serve the purpose.<br />
In real life situation SQLs are usually part of modules and codes. So using hint at SQL level, its not possible to implement the hint in code. Also, using hints in SQL at code level is not a good practice for obvious reason.</p>
<p>If we create a baseline based on hints than baseline will be automatically used for that SQL and plan will be same as that using hint.</p>
<p>Procedure is simple, just use the hint and run sql couple of times. One you do that, the plan will be automatically stored in shared_pool.</p>
<p>Find a SQL ID</p>
<pre>SQL&gt; select sql_id from v$sql where sql_text like 'select /*+ index(T_IDX T) +*/ * from%';

SQL_ID
-------------
50tsvs88gx382</pre>
<p>Use DBMS_SPM.load_plans_from_cursor_cache to create baseline from cursor cache.</p>
<pre>DECLARE
  l_plans_loaded  PLS_INTEGER;
BEGIN
  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
    sql_id =&gt; '50tsvs88gx382');
END;
/</pre>
<p>At this point we have 2 SQLs -</p>
<p>50tsvs88gx382 &#8211; using index hint<br />
5pvxxjg6n7mrp &#8211; Original query without using hint. This is doing FTS</p>
<pre>SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines ;

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  YES NO  NO
SYS_SQL_3f0d350a1c24a8d4       SYS_SQL_PLAN_1c24a8d4ae82cf72  YES YES NO

SQL&gt;</pre>
<p>SQL_HANDLE &#8211; <strong>SYS_SQL_1447ba3a1d83920f</strong> is for original query without hint. This was having only 1 baseline, but when we loaded the baseline for query <strong>50tsvs88gx382</strong> which is using hint, it automatically created the baseline for original query. 11g is smart enought to filter the hints and create a baseline for original query.</p>
<p>At this stage you have 2 option</p>
<address><span style="color:#000080;">1) Accept plan SYS_SQL_PLAN_1d83920fae82cf72 for SQL_HANDLE SYS_SQL_1447ba3a1d83920f</span><br />
<span style="color:#000080;">2) Link sql plan SYS_SQL_PLAN_1c24a8d4ae82cf72 of SQL_HANDLE SYS_SQL_3f0d350a1c24a8d4 to SQL_HANDLE SYS_SQL_1447ba3a1d83920f</span></address>
<p>You already know option 1.</p>
<p>Lets see option 2.</p>
<p>To link the plan of some other SQL_HANDLE (<strong>SYS_SQL_3f0d350a1c24a8d4</strong>) to our SQL_HANDLE (<strong>SYS_SQL_1447ba3a1d83920f</strong>), you can use same procedure dbms_spm.load_plans_from_cursor_cache</p>
<pre>DECLARE
  l_plans_loaded  PLS_INTEGER;
BEGIN
  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
    sql_id =&gt; '50tsvs88gx382',
    PLAN_HASH_VALUE =&gt; 470836197,
    SQL_HANDLE =&gt; 'SYS_SQL_1447ba3a1d83920f');
END;
/

PL/SQL procedure successfully completed.</pre>
<p>In above procedure,<br />
- SQL_ID is the new SQL_ID having hints.<br />
- PLAN_HASH_VALUE is the plan hash value of SQL with hints. This is the plan we want to assign to our SQL_HANDLE<br />
- SQL_HANDLE is the name of our SQL Handle to which we want to assign the plan</p>
<p>After assigning the plan, you will see the status as below.</p>
<pre>SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED from dba_sql_plan_baselines ;

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  YES YES NO
SYS_SQL_3f0d350a1c24a8d4       SYS_SQL_PLAN_1c24a8d4ae82cf72  YES YES NO

SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |  1048K|    11M|   465   (2)| 00:00:06 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |  1048K|    11M|   465   (2)| 00:00:06 |
|*  2 |   INDEX RANGE SCAN          | T_IDX |  1048K|       |   209   (2)| 00:00:03 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920fae82cf72" used for this statement

18 rows selected.

SQL&gt;</pre>
<p>Hope this helps !!</p>
<br /> Tagged: <a href='http://avdeo.com/tag/baseline/'>baseline</a>, <a href='http://avdeo.com/tag/dba_sql_plan_baselines/'>dba_sql_plan_baselines</a>, <a href='http://avdeo.com/tag/spm/'>spm</a>, <a href='http://avdeo.com/tag/sql-plan-baseline/'>sql plan baseline</a>, <a href='http://avdeo.com/tag/sql-plan-management/'>sql plan management</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/882/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/882/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/882/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/882/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/882/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/882/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/882/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/882/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=882&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/08/07/oracle-sql-plan-management-%e2%80%93-part-3/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle SQL Plan Management – Part 2</title>
		<link>http://avdeo.com/2011/06/07/oracle-sql-plan-management-%e2%80%93-part-2/</link>
		<comments>http://avdeo.com/2011/06/07/oracle-sql-plan-management-%e2%80%93-part-2/#comments</comments>
		<pubDate>Tue, 07 Jun 2011 18:10:49 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[baselines]]></category>
		<category><![CDATA[spm]]></category>
		<category><![CDATA[sql plan baselines]]></category>
		<category><![CDATA[sql plan management]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=874</guid>
		<description><![CDATA[SQL Plan Management – Oracle Database 11g In SPM part 1 we saw information about SPM and how to automatically capture the baseline. In this part we will see how to manually capture the baseline and the affect of using FIXED variable. Capturing Baseline Manually Occasionally we have to to capture the baseline manually. This [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=874&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1><span style="text-decoration:underline;"><span style="color:#000080;"><strong><strong>SQL Plan Management – Oracle Database 11g</strong></strong></span></span></h1>
<p>In SPM part 1 we saw information about SPM and how to automatically capture the baseline.<br />
In this part we will see how to manually capture the baseline and the affect of using FIXED variable.</p>
<h2><span style="color:#000080;">Capturing Baseline Manually</span></h2>
<p>Occasionally we have to to capture the baseline manually. This could happen while tuning the query in our database where we have optimizer_capture_sql_plan_baselines parameter set to FALSE.</p>
<p>We have 2 procedures available for capturing the baselines manually.</p>
<ol>
<li>
<h4><span style="color:#000080;">LOAD_PLANS_FROM_SQLSET</span></h4>
</li>
<li>
<h4><span style="color:#000080;">LOAD_PLANS_FROM_CURSOR_CACHE</span></h4>
</li>
</ol>
<h4></h4>
<p>Above procedures are part of DBMS_SPM packages.</p>
<p><strong>LOAD_PLANS_FROM_SQLSET</strong> procedure is used mainly while doing the upgrade from Oracle database 10g to Oracle database 11g.</p>
<p>The procedure is to</p>
<ol>
<li>create a SQL Tuning set in 10g and pack all the SQLs in the library cache along with there plans into SQL tuning set  &#8211; Procedure DBMS_SQLTUNE.CREATE_SQLSET and DBMS_SQLTUNE.LOAD_SQLSET</li>
<li>Then to create a staging table and load this SQL tuning set into the staging table &#8211; Procedure DBMS_SQLTUNE.CREATE_STGTAB_SQLSET and DBMS_SQLTUNE.PACK_STGTAB_SQLSET</li>
<li>Update database to 11g</li>
<li>Unpack the staging table into SQL Tuning set you created before &#8211; Procedure DBMS_SQLTUNE.UNPACK_STGTAB_SQLSET</li>
<li>Create SQL Baselines from the SQL tuning set &#8211; Procedure DBMS_SPM.LOAD_PLANS_FROM_SQLSET</li>
</ol>
<p><strong>LOAD_PLANS_FROM_CURSOR_CACHE</strong> is used after 11g upgrade when we have optimizer_capture_sql_plan_baselines set to false and we want to create baseline for a query in order to stablize the plan.</p>
<pre>

SQL&gt; select col1, count(1) from T group by col1;

      COL1   COUNT(1)
---------- ----------
         1          1
         2          3
         3      98304

SQL&gt; show parameters capture

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE

SQL&gt;</pre>
<p>Currently we dont have any baselines in the database.</p>
<pre>

SQL&gt; select sql_handle, plan_name, sql_text, enabled, accepted, fixed from dba_sql_plan_baselines;

no rows selected

SQL&gt;

SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; set line 999
SQL&gt; set pagesize 999
SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 49154 |  2976K|   260   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    | 49154 |  2976K|   260   (2)| 00:00:04 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

13 rows selected.

SQL&gt;</pre>
<p>Lets create a baseline manually for this statement. For creating baselines manually we need to have the statement in cache first.<br />
Lets run the statement once and find the SQL ID.</p>
<pre>

SQL&gt; select sql_id, sql_text from v$sql where sql_text like 'select * from T where%';

SQL_ID        SQL_TEXT
------------- ------------------------------------------------------------------------------------------
5pvxxjg6n7mrp select * from T where col1 = 1

Now we will use LOAD_PLANS_FROM_CURSOR_CACHE to create a baseline

SQL&gt; DECLARE
  2  l_plans_loaded  PLS_INTEGER;
  3  BEGIN
  4  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
  5  sql_id =&gt; '5pvxxjg6n7mrp');
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL&gt; select sql_handle, plan_name, sql_text, enabled, accepted, fixed from dba_sql_plan_baselines;

SQL_HANDLE                     PLAN_NAME                      SQL_TEXT                         ENA ACC FIX
------------------------------ ------------------------------ -------------------------------- --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  select * from T where col1 = 1   YES YES NO

SQL&gt;</pre>
<p>So we can see that SQL Plan baseline is created as well as accepted.<br />
We will check out the plan from baseline now, but it should be full table scan.</p>
<pre>

SQL&gt; SET LONG 10000
SQL&gt; select * from TABLE(DBMS_XPLAN.display_sql_plan_baseline(plan_name=&gt;'SYS_SQL_PLAN_1d83920f94ecae5c'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------
SQL handle: SYS_SQL_1447ba3a1d83920f
SQL text: select * from T where col1 = 1
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Plan name: SYS_SQL_PLAN_1d83920f94ecae5c
Enabled: YES     Fixed: NO      Accepted: YES     Origin: MANUAL-LOAD
--------------------------------------------------------------------------------

Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 49154 |  2976K|   260   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    | 49154 |  2976K|   260   (2)| 00:00:04 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

24 rows selected.

SQL&gt;

Now lets create an index on the table on COL1.

SQL&gt; create index T_IDX on T(COL1);

Index created.

SQL&gt;</pre>
<p>Now since the baseline is used, same query will go for a full table scan even after creating an index.</p>
<pre>

SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 49154 |  2976K|   260   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    | 49154 |  2976K|   260   (2)| 00:00:04 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920f94ecae5c" used for this statement

17 rows selected.

SQL&gt;</pre>
<p>So as you can see we have a baseline SYS_SQL_PLAN_1d83920f94ecae5c getting used for this query.</p>
<p>Lets go ahead and try creating another baseline for this SQL. May be this time we will get better plan.</p>
<p>SQL ID remains the same.</p>
<pre>

SQL&gt; DECLARE
  2  l_plans_loaded  PLS_INTEGER;
  3  BEGIN
  4  l_plans_loaded := DBMS_SPM.load_plans_from_cursor_cache(
  5  sql_id =&gt; '5pvxxjg6n7mrp');
  6  END;
  7  /

PL/SQL procedure successfully completed.

SQL&gt; select sql_handle, plan_name, sql_text, enabled, accepted, fixed from dba_sql_plan_baselines;

SQL_HANDLE                     PLAN_NAME                      SQL_TEXT                         ENA ACC FIX
------------------------------ ------------------------------ -------------------------------- --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  select * from T where col1 = 1   YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  select * from T where col1 = 1   YES NO  NO</pre>
<p>And yes, we can see Oracle has created another baseline here. But ACCEPTED is still NO for the new plan.<br />
This is because we haven&#8217;t evaluated the plan yet. If we would have set optimizer_capture_sql_plan_baselines parameter to true, it would have automatically captured and made ACCEPTED=YES after doing automatic evaluation.<br />
Since this is false, we have to evaluate whether new plan is better or not. This process of evaluating new baseline is called evolving.</p>
<p>Evolving a plan actually compares the cost and several other factors like DISK_READS, BUFFER_GETS, ELAPSED_TIME etc for all the plans that are available in DBA_SQL_PLAN_BASELINES table for that particular SQL HANDLE.<br />
So in our case when we evolve the plan it will compare plan SYS_SQL_PLAN_1d83920f94ecae5c and SYS_SQL_PLAN_1d83920fae82cf72</p>
<p>Just to be certain we will display the plan SYS_SQL_PLAN_1d83920fae82cf72</p>
<pre>

SQL&gt; select * from TABLE(DBMS_XPLAN.display_sql_plan_baseline(plan_name=&gt;'SYS_SQL_PLAN_1d83920fae82cf72'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------
SQL handle: SYS_SQL_1447ba3a1d83920f
SQL text: select * from T where col1 = 1
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Plan name: SYS_SQL_PLAN_1d83920fae82cf72
Enabled: YES     Fixed: NO      Accepted: NO      Origin: AUTO-CAPTURE
--------------------------------------------------------------------------------

Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       | 49154 |  2976K|     6   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     | 49154 |  2976K|     6   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IDX | 49154 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

25 rows selected.

SQL&gt;</pre>
<p>So it is indeed using the index on the table.</p>
<p>Here there are 2 things again.</p>
<ol>
<li>Evolving the plan automatically &#8211; Using procedure DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE</li>
<li>Manually accepting the plan &#8211; Using procedure ALTER_SQL_PLAN_BASELINE setting ACCEPTED=&gt;YES</li>
</ol>
<p>In the first method optimizer will evaluate based on all the factors (we will see those factors below) and &#8220;selects&#8221; the best plan. I have highlighted select here because optimizer is going to select from the set of existing plans, its not going to parse and create a whole other plan.<br />
So its upto the optimizer to decide which plan is best among the available plan.</p>
<p>In method 2, we can decide and select which ever plan we think is correct. This based on our knowledge of the type of SQL we are running and what resources we have with us.</p>
<h2>
<p><span style="color:#000080;">Can we have 2 plans in ACCEPTED status for a query?</span></h2>
<p>Yes we can.</p>
<h2>
<p><span style="color:#000080;">Which plan optimizer will choose out of the two?</span></h2>
<p>Always the best among the two. If more than 1 plan is ACCEPTED than optimizer will choose the best plan to be used for the query.<br />
Example if we use a query &#8220;select * from T where col = :B1&#8243;<br />
Here we have used a bind variable. Lets say we have 2 plans with us right now<br />
Plan 1) Full table scan<br />
Plan 2) Index Range scan</p>
<p>Which plan optimizer will choose depends upon the value of bind variable.<br />
Yes, in 11g we have something called &#8220;Adaptive Cursor Sharing&#8221;, but this is little off the topic. We will cover &#8220;Adaptive Cursor Sharing&#8221; in different article.</p>
<p>So if we supply value as 1 or 2 and since there is only 1 row with col1=1 and 3 rows with col1=2, optimizer will use Plan 2) Index Range Scan.<br />
If we supply value as 3, optimizer will use Plan 1) Full table scan.</p>
<p>So imagine a case where we have 5-6 plans based on selectivity of different tables involved in a complex query, in that case its a good idea to keep all those plans as ACCEPTED. Optimizer will always choose the best among those based on selectivity of the data.</p>
<p>We have seen evolving the plan in Part 1 &#8211; http://avdeo.com/2011/06/02/oracle-sql-plan-management-part-1/<br />
Lets set ACCEPTED=TRUE manually now.</p>
<pre>

SQL&gt; SET SERVEROUTPUT ON
SQL&gt; DECLARE
  2    l_plans_altered  PLS_INTEGER;
  3  BEGIN
  4    l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(
  5      sql_handle      =&gt; 'SYS_SQL_1447ba3a1d83920f',
  6      plan_name       =&gt; 'SYS_SQL_PLAN_1d83920fae82cf72',
  7      attribute_name  =&gt; 'ACCEPTED',
  8      attribute_value =&gt; 'YES');
  9
 10    DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
 11  END;
 12  /
Plans Altered: 1

PL/SQL procedure successfully completed.

SQL&gt;

SQL&gt; select sql_handle, plan_name, sql_text, enabled, accepted, fixed from dba_sql_plan_baselines;

SQL_HANDLE                     PLAN_NAME                      SQL_TEXT                         ENA ACC FIX
------------------------------ ------------------------------ -------------------------------- --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  select * from T where col1 = 1   YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  select * from T where col1 = 1   YES YES NO

SQL&gt;</pre>
<p>Lets check the explain plan for value 1.</p>
<pre>

SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       | 49154 |  2976K|    56   (2)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     | 49154 |  2976K|    56   (2)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IDX | 49154 |       |    10   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920fae82cf72" used for this statement

18 rows selected.

SQL&gt;</pre>
<p>So its using SYS_SQL_PLAN_1d83920fae82cf72 baselines.</p>
<h2>
<p><span style="color:#000080;">What is the affect of using FIXED=YES ?</span></h2>
<p>Fixed attribute will fix the plan for a query. So even if we have a better plan, the query will still not be using it. It is like disabling (ENABLED=NO, ACCEPTED=NO) all the plans for that SQL Handle.</p>
<p>Let make FIXED=YES for the first baseline (SYS_SQL_PLAN_1d83920f94ecae5c) which does full table scan.<br />
To change this attribute we can again use DBMS_SPM.ALTER_SQL_PLAN_BASELINE procedure</p>
<pre>

SQL&gt; set serveroutput on
SQL&gt; DECLARE
  2    l_plans_altered  PLS_INTEGER;
  3  BEGIN
  4    l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(
  5      sql_handle      =&gt; 'SYS_SQL_1447ba3a1d83920f',
  6      plan_name       =&gt; 'SYS_SQL_PLAN_1d83920f94ecae5c',
  7      attribute_name  =&gt; 'FIXED',
  8      attribute_value =&gt; 'YES');
  9
 10    DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
 11  END;
 12  /
Plans Altered: 1

PL/SQL procedure successfully completed.

SQL&gt;

SQL&gt; select sql_handle, plan_name, sql_text, enabled, accepted, fixed from dba_sql_plan_baselines;

SQL_HANDLE                     PLAN_NAME                      SQL_TEXT                                           ENA ACC FIX
------------------------------ ------------------------------ -------------------------------------------------- --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  select * from T where col1 = 1                     YES YES YES
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  select * from T where col1 = 1                     YES YES NO

SQL&gt;</pre>
<p>Lets check out the explain plan for &#8220;select * from T where col1 = 1&#8243; query</p>
<pre>

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 49154 |  2976K|   260   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| T    | 49154 |  2976K|   260   (2)| 00:00:04 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920f94ecae5c" used for this statement

17 rows selected.

SQL&gt;</pre>
<p>So if you see now, same query which was earlier using index scan has now shifted to full table scan. Thats the magic of SPM !!<br />
I would recommend not using FIXED attribute at all. You are just killing the functionality provided by 11g.</p>
<p>However, if we make both plans as FIXED then ??</p>
<pre>

set serveroutput on                                           
DECLARE                                                       
  l_plans_altered  PLS_INTEGER;                               
BEGIN                                                         
  l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(        
    sql_handle      =&gt; 'SYS_SQL_1447ba3a1d83920f',            
    plan_name       =&gt; 'SYS_SQL_PLAN_1d83920fae82cf72',       
    attribute_name  =&gt; 'FIXED',                               
    attribute_value =&gt; 'YES');                                
                                                              
  DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
END;                                                          
/                                                             

SQL&gt; select sql_handle, plan_name, sql_text, enabled, accepted, fixed from dba_sql_plan_baselines;

SQL_HANDLE                     PLAN_NAME                      SQL_TEXT                                           ENA ACC FIX
------------------------------ ------------------------------ -------------------------------------------------- --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  select * from T where col1 = 1                     YES YES YES
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  select * from T where col1 = 1                     YES YES YES

SQL&gt; explain plan for
  2  select * from T where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       | 49154 |  2976K|     6   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     | 49154 |  2976K|     6   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IDX | 49154 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920fae82cf72" used for this statement

18 rows selected.

SQL&gt;</pre>
<p>It will again go back to best among the fixed plans.</p>
<p>In the next part, I will cover how to transfer the baseline from one database to another and also how to set a specific plan for a query using hint and then creating baseline for that.</p>
<p>Hope this helps !!</p>
<p>&nbsp;</p>
<br /> Tagged: <a href='http://avdeo.com/tag/baselines/'>baselines</a>, <a href='http://avdeo.com/tag/spm/'>spm</a>, <a href='http://avdeo.com/tag/sql-plan-baselines/'>sql plan baselines</a>, <a href='http://avdeo.com/tag/sql-plan-management/'>sql plan management</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/874/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/874/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/874/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/874/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/874/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/874/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/874/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/874/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=874&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/06/07/oracle-sql-plan-management-%e2%80%93-part-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle SQL Plan Management &#8211; Part 1</title>
		<link>http://avdeo.com/2011/06/02/oracle-sql-plan-management-part-1/</link>
		<comments>http://avdeo.com/2011/06/02/oracle-sql-plan-management-part-1/#comments</comments>
		<pubDate>Thu, 02 Jun 2011 12:52:34 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Database 10g Performance Tuning]]></category>
		<category><![CDATA[Oracle Database 10g]]></category>
		<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[DBMS_SPM]]></category>
		<category><![CDATA[LOAD_PLAN_FROM_CURSOR_CACHE]]></category>
		<category><![CDATA[LOAD_PLAN_FROM_SQLSET]]></category>
		<category><![CDATA[spm]]></category>
		<category><![CDATA[sql plan baselines]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=868</guid>
		<description><![CDATA[SQL Plan Management &#8211; Oracle Database 11g SQL Plan Management or SPM is a new feature introduced in 11g. We will take a detailed look at SPM in the following sessions. Before starting with practical example lets see some theory. What is SQL Plan Management? SPM is a new feature introduced in Oracle database 11g [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=868&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<h1><span style="text-decoration:underline;color:#000080;"><strong>SQL Plan Management &#8211; Oracle Database 11g</strong></span></h1>
<h2></h2>
<p>SQL Plan Management or SPM is a new feature introduced in 11g. We will take a detailed look at SPM in the following sessions.<br />
Before starting with practical example lets see some theory.</p>
<h2><span style="color:#000080;">What is SQL Plan Management?</span></h2>
<p>SPM is a new feature introduced in Oracle database 11g which stores the baseline (Plans + Hints) inside database.<br />
SPM allows an Oracle DBA to capture and preserve the most efficient execution plans for any SQL statement, thus limiting the impact of refreshed optimizer statistics, changes to existing applications, and even upgraded database versions</p>
<h2><span style="color:#000080;">Why do we need SPM?</span></h2>
<p>SPM is basically used for plan stability. If you have a database environment with several queries running, you always want your queries to run the way they are running irrespective of the changes that you make in your environment.<br />
Example, If you upgrade your database, your queries might behave differently because of the change in optimizer or change in environment and at initial run you have to fix many queries in your production DB because of the upgrade or change in the env.<br />
To avoid this, SPM is introduce to give you plan stability. So even after change in the environment, your queries will use same plan as it was before. More plans (Better or worse) could exists in the new environment, but optimizer is not allowed to use those plans without you confirming the plan change.</p>
<h2><span style="color:#000080;">What was wrong with outlines?</span></h2>
<p>Well, outlines are more about fixing the plan for a query that optimizer will use. So if there is change in environment, the plan would still be the same.<br />
There are certain situations where you want the plan to change with change in lets say data. What if your data gets skewed over time.</p>
<p>Intially you had 100 of entries for month &#8220;DEC&#8221; out of total 150 entries. So it was using FTS. Now with increase in the data, there are 1 million records and entries for month &#8220;DEC&#8221; are around 1000. In that case it makes sense for optimizer to change plan and start using Index scan instead of FTS.<br />
But since you used outline, you are forcing optimizer to go for a FTS. This is just an example situation and things can change in your environment and so outline is not a very good approach for such situations.</p>
<p><span style="color:#000080;">What was wrong with profile?</span></p>
<p>Profile is another feature introduced in 10g and can be implemented at SQL level. Profiles are better than outlines in that they are not fixing a plan through out the life of SQL. With change in the environment the plans can change even if the profile is used.</p>
<h2><span style="color:#000080;">So whats the difference between profile and SQL plan baselines?</span></h2>
<p>Profile is more of a advisors. They give advice to optimizer while executing the query. They provide optimizer with all the precise estimates. Profiles are more abount correcting optimizer to use correct plan when the underlying data is skewed and changed drastically.<br />
The goal is to create best execution plan for the SQL by giving the very precise data to the optimizer. Its the optimizer who will decide what should be the explain plan based on the information/hints it has received from profile.</p>
<p>SQL Plan baselines works differently. It enforces the plan to be used for a SQL. Baseline does not provide and estimates or it does not help optimizer in anyway. It just tells optimizer to ignore everything and use the plan that we are giving you.<br />
Optimizer just followes the plan provided by baselines. So here baseline is the driving mechanism for getting the correct plan.</p>
<h2><span style="color:#000080;">Finally how baselines are different then outline then?</span></h2>
<p>Well, baseline always keeps the optimized plans for your SQL. If there is a change in the environment you will have a new baseline created for the same SQL. Oracle will stop that baseline in the baseline history.<br />
Depending on the baseline parameters setting in your environment, new plan will be automatically used or you have to evolve the new plan for optimizer to use it.</p>
<p>So in a way SQL baselines are combination of outlines and profiles. It gives the stability of plan similar to outlines and it also allows capturing better plans in case the environment changes.</p>
<p>Not only that, SQL Baselines give the complete control to the DBA on</p>
<ol>
<li>Whether to capture the new and better plans?</li>
<li>Whether to use the new plans automaticallly without DBA&#8217;s intervention.</li>
</ol>
<p>So DBAs have complete control of the environment now. Far better than profiles and outlines.</p>
<p><span style="text-decoration:underline;"><strong>SQL Plan Baseline Parameters:</strong></span></p>
<p>Before we check how to use SQL Plan baselines, lets consider the significance of 2 important baseline parameters</p>
<h3><span style="color:#000080;">1) optimizer_capture_sql_plan_baselines &#8211; Default &#8220;FALSE&#8221;</span></h3>
<p>This parameter is responsible for automatic capturing the baselines for SQLs. If we set this parameter to TRUE we are asking oracle to automatically gather the baselines for the SQL.<br />
When you run the query for the first time (and parsed version is not present in shared_pool), oracle consider that as a fresh new query and does not create a baseline.<br />
When you run the query for second time, oracle will consider the query as repetative and will automatically create the baseline.<br />
These baseline are stored in DBA_SQL_PLAN_BASELINES table.</p>
<p>If this parameter is set to FALSE, then we (DBA) has to create baselines for the SQL manually. There are 2 procedure available for creating baselines manually.</p>
<h5 style="padding-left:30px;"><span style="color:#000000;"><strong>1) Using DBMS_SPM.LOAD_PLANS_FROM_SQLSET</strong></span></h5>
<p style="padding-left:30px;">This procedure is usually used when we create SQL tuning set and store our SQLs into the tuning sets. Normally done before we upgrade the database to 11g. In our 10g database we create SQL tuning set and store all our SQL. Once we upgrade to 11g, we can create baselines for all our plans in SQL tuning set. That why what ever plans were effective in 10g, same will be used in 11g and there wont be any plan flips.</p>
<h5 style="padding-left:30px;"><strong><span style="color:#000000;">2) Using DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE</span></strong></h5>
<p style="padding-left:30px;">This is used when we want to fix one of the SQL currently running in our 11g database. We just load the plans from cursor cache (shared_pool) and create baseline out of that. We need to give SQL ID as input to this procedure.</p>
<p>We will see how to create baseline using manual method at later point of time.</p>
<h3><span style="color:#000080;">2) optimizer_use_sql_plan_baselines &#8211; Default &#8220;TRUE&#8221;</span></h3>
<p>This parameter will allow optimizer to use the baselines present in DBA_SQL_PLAN_BASELINES table. If you set this parameter to FALSE, then your 11g DB will start behaving same as 10g DB.<br />
If there is any change in environment then it might flip the plan. Keeping this parameter TRUE is important in 11g.</p>
<h2><span style="color:#000080;">How to use SQL Plan Management baselines ?</span></h2>
<p>Lets take an example in a test database.</p>
<p>Table T with 1540 records.</p>
<pre>SQL&gt; select count(1) from t;

  COUNT(1)
----------
      1540</pre>
<p>Data is skewed and distribution is as given below.</p>
<pre>SQL&gt; select col1, count(1) from t group by col1;

      COL1   COUNT(1)
---------- ----------
         1          1
         2          3
         3       1536</pre>
<p>Gather the stats on the table</p>
<pre>SQL&gt; exec dbms_stats.gather_table_stats(OWNNAME=&gt; 'ADVAITD_DBA',TABNAME =&gt; 'T', DEGREE =&gt; 6, GRANULARITY =&gt; 'ALL' ,CASCADE =&gt; TRUE , METHOD_OPT =&gt; 'FOR ALL INDEXED COLUMNS SIZE 254');

SQL&gt;

Currently I dont have any baseline.

SQL&gt; select count(1) from dba_sql_plan_baselines;

  COUNT(1)
----------
         0

SQL&gt;</pre>
<p>My baseline parameters setting is as below.</p>
<pre>SQL&gt; show parameters baselines

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
optimizer_capture_sql_plan_baselines boolean     FALSE
optimizer_use_sql_plan_baselines     boolean     TRUE
SQL&gt;</pre>
<p>Let us first consider the auto capture utility for baselines.</p>
<h2><span style="color:#000080;">AUTO Capture of baseline</span></h2>
<pre>SQL&gt; alter session set optimizer_capture_sql_plan_baselines=TRUE;

Session altered.

SQL&gt;</pre>
<p>As mention earlier, we need to run the query 2 times in order to automatically create the baseline.</p>
<pre>SQL&gt; select * from t where col1 = 1;

      COL1 COL2                                               COL3
---------- -------------------------------------------------- -----------
         1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01-JUN-2011

SQL&gt; select * from t where col1 = 1;

      COL1 COL2                                               COL3
---------- -------------------------------------------------- -----------
         1 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 01-JUN-2011</pre>
<p>If we check DBA_SQL_PLAN_BASELINES we will see a sql baseline created.</p>
<pre>SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED
  2  from dba_sql_plan_baselines
  3  WHERE sql_text like 'select * from t%';

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO</pre>
<p>Turning off auto SQL plan baseline capture</p>
<pre>SQL&gt; alter session set optimizer_capture_sql_plan_baselines=FALSE;

Session altered.

SQL&gt;</pre>
<p>Following statement gives the plan stored in the baseline. DBMS_XPLAN has a new procedure DISPLAY_SQL_PLAN_BASELINE which will display the baseline.</p>
<pre>SQL&gt; set line 999
SQL&gt; set pagesize 999
SQL&gt; select * from table(dbms_xplan.display_sql_plan_baseline(plan_name=&gt;'SYS_SQL_PLAN_1d83920f94ecae5c'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------
SQL handle: SYS_SQL_1447ba3a1d83920f
SQL text: select * from t where col1 = 1
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Plan name: SYS_SQL_PLAN_1d83920f94ecae5c
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE
--------------------------------------------------------------------------------

Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    15 |   735 |     9   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |    15 |   735 |     9   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

24 rows selected.

SQL&gt;</pre>
<p>Origin: AUTO-CAPTURE shown above tell us that this baseline is captured automatically.</p>
<p>Lets now create an index and gather stats over index.</p>
<pre>SQL&gt; create index t_idx on t(col1);

Index created.

SQL&gt; exec DBMS_STATS.GATHER_INDEX_STATS(OWNNAME =&gt; 'ADVAITD_DBA', INDNAME=&gt;'T_IDX');</pre>
<p>Run the same query now, since the index is created, we expect the query to use the index.</p>
<pre>SQL&gt; explain plan for
  2  select * from t where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1601196873

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |    15 |   735 |     9   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |    15 |   735 |     9   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920f94ecae5c" used for this statement

17 rows selected.

SQL&gt;</pre>
<p>The reason we are seeing full table scan is because of the NOTE at the end, which says &#8220;SQL plan baseline &#8220;SYS_SQL_PLAN_1d83920f94ecae5c&#8221; used for this statement&#8221;</p>
<p>Since we have a baseline created for this SQL, it will not allow the plan to be changed. This is the kind of stability that SQL Plan baseline gives.<br />
But using an index will be beneficial in our case.</p>
<p>If we check DBA_SQL_PLAN_BASELINES we can see a new plan has been created (PLAN_NAME = SYS_SQL_PLAN_1d83920fae82cf72), but it is not yet ACCEPTED. The plan is enabled though.</p>
<pre>SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED
  2  from dba_sql_plan_baselines
  3  WHERE sql_text like 'select * from t%';

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  YES NO  NO</pre>
<p>We can check what the new plan looks like using dbms_xplan.display_sql_plan_baseline</p>
<pre>SQL&gt; select * from table(dbms_xplan.display_sql_plan_baseline(plan_name=&gt;'SYS_SQL_PLAN_1d83920fae82cf72'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------
SQL handle: SYS_SQL_1447ba3a1d83920f
SQL text: select * from t where col1 = 1
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Plan name: SYS_SQL_PLAN_1d83920fae82cf72
Enabled: YES     Fixed: NO      Accepted: NO      Origin: AUTO-CAPTURE
--------------------------------------------------------------------------------

Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    15 |   735 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |    15 |   735 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IDX |     6 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

25 rows selected.

SQL&gt;</pre>
<p>As seen above, new plan uses index. Lets evolve this plan now.<br />
Evolving a plan includes evaluating the cost of the plan and accepting if the plan seems to be better than all accepted plan for this query.</p>
<pre>SQL&gt; SELECT DBMS_SPM.evolve_sql_plan_baseline(sql_handle =&gt; 'SYS_SQL_1447ba3a1d83920f') from dual;

DBMS_SPM.EVOLVE_SQL_PLAN_BASELINE(SQL_HANDLE=&gt;'SYS_SQL_1447BA3A1D83920F')
--------------------------------------------------------------------------------

-------------------------------------------------------------------------------
                        Evolve SQL Plan Baseline Report
-------------------------------------------------------------------------------

Inputs:
-------
  SQL_HANDLE = SYS_SQL_1447ba3a1d83920f
  PLAN_NAME  =
  TIME_LIMIT = DBMS_SPM.AUTO_LIMIT
  VERIFY     = YES
  COMMIT     = YES

Plan: SYS_SQL_PLAN_1d83920fae82cf72
-----------------------------------
  Plan was verified: Time used .01 seconds.
  Passed performance criterion: Compound improvement ratio &gt;= 7.33
  Plan was changed to an accepted plan.

                      Baseline Plan      Test Plan     Improv. Ratio
                      -------------      ---------     -------------
  Execution Status:        COMPLETE       COMPLETE
  Rows Processed:                 1              1
  Elapsed Time(ms):               0              0
  CPU Time(ms):                   0              0
  Buffer Gets:                   22              3              7.33
  Disk Reads:                     0              0
  Direct Writes:                  0              0
  Fetches:                        0              0
  Executions:                     1              1

-------------------------------------------------------------------------------
                                 Report Summary
-------------------------------------------------------------------------------
Number of SQL plan baselines verified: 1.
Number of SQL plan baselines evolved: 1.</pre>
<p>Sometimes, your plan may not get evolved because oracle see that there are other already ACCEPTED plans which are better than the plan you are trying to evolve.<br />
But if you know your plan will be better and still want to deploy the same, you can do so by manually changing the attributes ACCEPTED and ENABLED as shown below.</p>
<pre>SET SERVEROUTPUT ON
DECLARE
  l_plans_altered  PLS_INTEGER;
BEGIN
  l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(
    sql_handle      =&gt; 'SYS_SQL_1447ba3a1d83920f',
    plan_name       =&gt; 'SYS_SQL_PLAN_1d83920fae82cf72',
    attribute_name  =&gt; 'ENABLED',
    attribute_value =&gt; 'YES');

  DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
END;
/

SET SERVEROUTPUT ON
DECLARE
  l_plans_altered  PLS_INTEGER;
BEGIN
  l_plans_altered := DBMS_SPM.alter_sql_plan_baseline(
    sql_handle      =&gt; 'SYS_SQL_1447ba3a1d83920f',
    plan_name       =&gt; 'SYS_SQL_PLAN_1d83920fae82cf72',
    attribute_name  =&gt; 'ACCEPTED',
    attribute_value =&gt; 'YES');

  DBMS_OUTPUT.put_line('Plans Altered: ' || l_plans_altered);
END;
/</pre>
<p>You can also set the value of attribute FIXED using the above function. Here is the meaning of ENABLED, ACCPETED and FIXED</p>
<address><span style="color:#000080;">ENABLED   &#8211; &#8216;YES&#8217; means the plan is available for use by the optimizer. It may or may not be used depending on accepted status.</span><br />
<span style="color:#000080;">ACCPETED &#8211; &#8216;YES&#8217; means the plan will be used by optimizer while running the query. &#8216;NO&#8217; means optimizer will not use the plan.</span><br />
<span style="color:#000080;">FIXED        &#8211; &#8216;YES&#8217; means the SQL plan baseline is not evolved over time. A fixed plan takes precedence over a non-fixed plan.</span></address>
<p>Once you evolve the plan, you can see that plan is ACCEPTED now.</p>
<pre>SQL&gt; select SQL_HANDLE, PLAN_NAME, ENABLED, ACCEPTED, FIXED
  2  from dba_sql_plan_baselines
  3  WHERE sql_text like 'select * from t%';

SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX
------------------------------ ------------------------------ --- --- ---
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920f94ecae5c  YES YES NO
SYS_SQL_1447ba3a1d83920f       SYS_SQL_PLAN_1d83920fae82cf72  YES YES NO</pre>
<p>Now if you run the explain plan you can see Index T_IDX is getting used.</p>
<pre>SQL&gt; explain plan for
  2  select * from t where col1 = 1;

Explained.

SQL&gt; select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 470836197

-------------------------------------------------------------------------------------
| Id  | Operation                   | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |       |    15 |   735 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T     |    15 |   735 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IDX |     6 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------

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

   2 - access("COL1"=1)

Note
-----
   - SQL plan baseline "SYS_SQL_PLAN_1d83920fae82cf72" used for this statement

18 rows selected.

SQL&gt;</pre>
<p>Hope this helps.</p>
<p>Part 2 can be viewed at -<a href="http://avdeo.com/2011/06/07/oracle-sql-plan-management-%e2%80%93-part-2/" target="_blank">http://avdeo.com/2011/06/07/oracle-sql-plan-management-%E2%80%93-part-2/</a></p>
<h1><span style="text-decoration:underline;color:#000080;"><strong>References:</strong></span></h1>
<p>http://download.oracle.com/docs/cd/B28359_01/server.111/b28274/optplanmgmt.htm</p>
<p>http://www.comp.dit.ie/btierney/oracle11gdoc/appdev.111/b28419/d_spm.htm</p>
<br />Filed under: <a href='http://avdeo.com/category/database-10g-performance-tuning/'>Database 10g Performance Tuning</a>, <a href='http://avdeo.com/category/oracle-database-10g/'>Oracle Database 10g</a>, <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a> Tagged: <a href='http://avdeo.com/tag/dbms_spm/'>DBMS_SPM</a>, <a href='http://avdeo.com/tag/load_plan_from_cursor_cache/'>LOAD_PLAN_FROM_CURSOR_CACHE</a>, <a href='http://avdeo.com/tag/load_plan_from_sqlset/'>LOAD_PLAN_FROM_SQLSET</a>, <a href='http://avdeo.com/tag/spm/'>spm</a>, <a href='http://avdeo.com/tag/sql-plan-baselines/'>sql plan baselines</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/868/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/868/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/868/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=868&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/06/02/oracle-sql-plan-management-part-1/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Creating Standby database using Active Duplication &#8211; Oracle Database 11g</title>
		<link>http://avdeo.com/2011/05/09/creating-standby-database-using-active-duplication-oracle-database-11g/</link>
		<comments>http://avdeo.com/2011/05/09/creating-standby-database-using-active-duplication-oracle-database-11g/#comments</comments>
		<pubDate>Mon, 09 May 2011 14:51:44 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[active database duplication]]></category>
		<category><![CDATA[active duplication]]></category>
		<category><![CDATA[creating database from existing database]]></category>
		<category><![CDATA[creating standby]]></category>
		<category><![CDATA[creating standby without taking backup]]></category>
		<category><![CDATA[oracle database 11g]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=852</guid>
		<description><![CDATA[Introduction: Oracle database 11g introduced a new feature called Active database duplication. Using this feature you can create a new database (primary/standby) from your current running database. This feature does not needs any backup to be taken, nor we have to do any restore. Creating active duplication is a RMAN feature and command for creating [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=852&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p><span style="text-decoration:underline;"><strong>Introduction:</strong></span></p>
<p>Oracle database 11g introduced a new feature called Active database duplication. Using this feature you can create a new database (primary/standby) from your current running database. This feature does not needs any backup to be taken, nor we have to do any restore.</p>
<p>Creating active duplication is a RMAN feature and command for creating active duplication comes with various options.</p>
<p>Following is the command used for active duplication</p>
<p><strong>duplicate target database to &lt;DB_NAME&gt; from active database;</strong></p>
<p>Following are the various arguments that we can pass to this command</p>
<p><span style="text-decoration:underline;">FROM ACTIVE DATABASE:</span> (This is supplied if we want to do active database duplication)</p>
<p>Specifies that the files for the standby database should be provided directly from the source database and not from a backup of the source database</p>
<p><span style="text-decoration:underline;">NOFILENAMECHECK:</span></p>
<p>Prevents RMAN from checking whether datafiles of the source database share the same names as the standby database files that are in use.</p>
<p>The NOFILENAMECHECK option is required when the standby and primary datafiles and online redo logs have identical filenames. Thus, if you want the duplicate database filenames to be the same as the source database filenames, and if the databases are in different hosts, then you must specify NOFILENAMECHECK</p>
<p><span style="text-decoration:underline;">SPFILE:</span></p>
<p>Copies the server parameter file from the source database to the operating system-specific default location for this file on the standby database.</p>
<p>RMAN uses the server parameter file to start the auxiliary instance for standby database creation. Any remaining options of the DUPLICATE command are processed after the database instance is started with the server parameter file.</p>
<p>If you execute DUPLICATE with the SPFILE clause, then the auxiliary instance must already be started with a text-based initialization parameter file. In this case, the only required parameter in the temporary initialization parameter file is DB_NAME, which can be set to any arbitrary value. RMAN copies the binary server parameter file, modifies the parameters based on the settings in the SPFILE clause, and then restarts the standby instance with the server parameter file. When you specify SPFILE, RMAN never uses the temporary text-based initialization parameter file to start the instance.</p>
<p>If FROM ACTIVE DATABASE is specified on DUPLICATE, then a server parameter file must be in use by the source database instance. If FROM ACTIVE DATABASE is not specified on DUPLICATE, then RMAN restores a backup of the server parameter file to the standby database.</p>
<p><span style="text-decoration:underline;">PARAMETER_VALUE_CONVERT:</span></p>
<p>Replaces the first string with the second string in all matching initialization parameter values. Note that DB_FILE_NAME_CONVERT and LOG_FILE_NAME_CONVERT are exceptions to this rule and are not affected.</p>
<p>You can use PARAMETER_VALUE_CONVERT to set a collection of initialization parameter values and avoid explicitly setting them all. For example, if the source database uses disk group +ALPHA while the standby database will use +BETA, then you could modify all parameters that refer to these disk groups by specifying SPFILE PARAMETER_VALUE_CONVERT (&#8216;+ALHPA&#8217;,'+BETA&#8217;).</p>
<p><span style="text-decoration:underline;">DORECOVER:</span></p>
<p>Specifies that RMAN should recover the standby database after creating it. If you specify an untilClause, then RMAN recovers to the specified SCN or time and leaves the database mounted.</p>
<p>RMAN leaves the standby database mounted after media recovery is complete, but does not place the standby database in manual or managed recovery mode. After RMAN creates the standby database, you must resolve any gap sequence before placing it in manual or managed recovery mode, or opening it in read-only mode.</p>
<p>For more details on arguments to be supplied check &#8211; http://download.oracle.com/docs/cd/B28359_01/backup.111/b28273/rcmsynta020.htm</p>
<p>Following is one example where I created a standby database using active database duplication.</p>
<p><span style="text-decoration:underline;"><strong>Pre-requisite:</strong></span></p>
<p>We should have a primary database up and running<br />
pfile, spfile and listener.ora file should be available for both primary and standby<br />
All the relevent directories for datafiles and diagnostic dest should be present<br />
Password file for standby should be present<br />
Entry should exist in /etc/oratab for both primary and standby</p>
<p>Steps for active database duplication</p>
<p><span style="text-decoration:underline;"><strong>Step 1) nomount the standby database</strong></span></p>
<pre>sqlplus "/as sysdba"

SQL*Plus: Release 11.1.0.7.0 - Production on Wed May 4 06:53:47 2011

Copyright (c) 1982, 2008, Oracle.  All rights reserved.

Connected to an idle instance.

SQL&gt; startup nomount
ORA-32004: obsolete and/or deprecated parameter(s) specified
ORACLE instance started.

Total System Global Area 2321612800 bytes
Fixed Size                  2174128 bytes
Variable Size            1198015312 bytes
Database Buffers         1073741824 bytes
Redo Buffers               47681536 bytes
SQL&gt;</pre>
<p><span style="text-decoration:underline;"><strong><br />
Step 2) Check the unique name for standby database</strong></span></p>
<pre>SQL&gt; show parameters uniq

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_unique_name                       string      orcl_a</pre>
<p><span style="text-decoration:underline;"><strong>Step 3) Start active duplication</strong></span></p>
<pre>rman target sys/&lt;password&gt;@orcl1 auxiliary=sys/&lt;password&gt;@orcl1_a

Recovery Manager: Release 11.1.0.7.0 - Production on Wed May 4 07:01:22 2011

Copyright (c) 1982, 2007, Oracle.  All rights reserved.

connected to target database: ORCL1 (DBID=998984585)
connected to auxiliary database: ORCL1 (not mounted)

RMAN&gt; duplicate target database to orcl1 from active database nofilenamecheck; --&gt; This will create a new primary database again
RMAN&gt; duplicate target database for standby from active  database nofilenamecheck; --&gt; This will create a new standby database

Starting Duplicate Db at 04-MAY-11
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=1122 device type=DISK

contents of Memory Script:
{
   backup as copy reuse
   file  '/opt/app/oracle/product/11.1.0.7/A24db/dbs/orapworcl1' auxiliary format
 '/opt/app/oracle/product/11.1.0.7/A24db/dbs/orapworcl1'   ;
}
executing Memory Script

Starting backup at 04-MAY-11
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=1109 device type=DISK
Finished backup at 04-MAY-11

contents of Memory Script:
{
   backup as copy current controlfile for standby auxiliary format  '/ctl-01/databases/orcl1/control.ctl';
   restore clone controlfile to  '/ctl-02/databases/orcl1/control.ctl' from
 '/ctl-01/databases/orcl1/control.ctl';
   sql clone 'alter database mount standby database';
}
executing Memory Script

Starting backup at 04-MAY-11
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
copying standby control file
output file name=/opt/app/oracle/product/11.1.0.7/A24db/dbs/snapcf_orcl1.f tag=TAG20110504T072433 RECID=2 STAMP=750237875
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:07
Finished backup at 04-MAY-11

Starting restore at 04-MAY-11
using channel ORA_AUX_DISK_1

channel ORA_AUX_DISK_1: copied control file copy
Finished restore at 04-MAY-11

sql statement: alter database mount standby database

contents of Memory Script:
{
   set newname for tempfile  1 to
 "/fs-b01-a/databases/orcl1/temp-01.dbf";
   set newname for tempfile  2 to
 "/fs-a01-a/databases/orcl1/dba_temp-01.dbf";
   set newname for tempfile  3 to
 "/fs-a01-a/databases/orcl1/temp-02.dbf";
   switch clone tempfile all;
   set newname for datafile  1 to
 "/fs-b01-a/databases/orcl1/system-01.dbf";
   set newname for datafile  2 to
 "/fs-a01-a/databases/orcl1/undo_t1-01.dbf";
   set newname for datafile  3 to
 "/fs-a01-a/databases/orcl1/sysaux-01.dbf";
   set newname for datafile  4 to
 "/fs-a01-a/databases/orcl1/administrator-01.dbf";
   set newname for datafile  5 to
 "/fs-b01-a/databases/orcl1/administrator_idx-01.dbf";
   set newname for datafile  6 to
 "/fs-a01-a/databases/orcl1/replication-01.dbf";
   set newname for datafile  7 to
 "/fs-b01-a/databases/orcl1/replication_idx-01.dbf";
   set newname for datafile  8 to
 "/fs-a01-a/databases/orcl1/rcvcat-001.dbf";
   set newname for datafile  9 to
 "/fs-b01-a/databases/orcl1/rcvcat_idx-001.dbf";
   set newname for datafile  10 to
 "/fs-d01-a/databases/orcl1/sysaux-20090310204613.dbf";
   set newname for datafile  11 to
 "/fs-d01-a/databases/orcl1/system-20090421171504.dbf";
   backup as copy reuse
   datafile  1 auxiliary format
 "/fs-b01-a/databases/orcl1/system-01.dbf"   datafile
 2 auxiliary format
 "/fs-a01-a/databases/orcl1/undo_t1-01.dbf"   datafile
 3 auxiliary format
 "/fs-a01-a/databases/orcl1/sysaux-01.dbf"   datafile
 4 auxiliary format
 "/fs-a01-a/databases/orcl1/administrator-01.dbf"   datafile
 5 auxiliary format
 "/fs-b01-a/databases/orcl1/administrator_idx-01.dbf"   datafile
 6 auxiliary format
 "/fs-a01-a/databases/orcl1/replication-01.dbf"   datafile
 7 auxiliary format
 "/fs-b01-a/databases/orcl1/replication_idx-01.dbf"   datafile
 8 auxiliary format
 "/fs-a01-a/databases/orcl1/rcvcat-001.dbf"   datafile
 9 auxiliary format
 "/fs-b01-a/databases/orcl1/rcvcat_idx-001.dbf"   datafile
 10 auxiliary format
 "/fs-d01-a/databases/orcl1/sysaux-20090310204613.dbf"   datafile
 11 auxiliary format
 "/fs-d01-a/databases/orcl1/system-20090421171504.dbf"   ;
   sql 'alter system archive log current';
}
executing Memory Script

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

renamed tempfile 1 to /fs-b01-a/databases/orcl1/temp-01.dbf in control file
renamed tempfile 2 to /fs-a01-a/databases/orcl1/dba_temp-01.dbf in control file
renamed tempfile 3 to /fs-a01-a/databases/orcl1/temp-02.dbf in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting backup at 04-MAY-11
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
input datafile file number=00008 name=/fs-a01-a/databases/orcl1/rcvcat-001.dbf
output file name=/fs-a01-a/databases/orcl1/rcvcat-001.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:02:05
channel ORA_DISK_1: starting datafile copy
input datafile file number=00009 name=/fs-b01-a/databases/orcl1/rcvcat_idx-001.dbf
output file name=/fs-b01-a/databases/orcl1/rcvcat_idx-001.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:02:05
channel ORA_DISK_1: starting datafile copy
input datafile file number=00010 name=/fs-d01-a/databases/orcl1/sysaux-20090310204613.dbf
output file name=/fs-d01-a/databases/orcl1/sysaux-20090310204613.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:15
channel ORA_DISK_1: starting datafile copy
input datafile file number=00011 name=/fs-d01-a/databases/orcl1/system-20090421171504.dbf
output file name=/fs-d01-a/databases/orcl1/system-20090421171504.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:01:05
channel ORA_DISK_1: starting datafile copy
input datafile file number=00002 name=/fs-a01-a/databases/orcl1/undo_t1-01.dbf
output file name=/fs-a01-a/databases/orcl1/undo_t1-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00004 name=/fs-a01-a/databases/orcl1/administrator-01.dbf
output file name=/fs-a01-a/databases/orcl1/administrator-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00005 name=/fs-b01-a/databases/orcl1/administrator_idx-01.dbf
output file name=/fs-b01-a/databases/orcl1/administrator_idx-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00006 name=/fs-a01-a/databases/orcl1/replication-01.dbf
output file name=/fs-a01-a/databases/orcl1/replication-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00007 name=/fs-b01-a/databases/orcl1/replication_idx-01.dbf
output file name=/fs-b01-a/databases/orcl1/replication_idx-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:25
channel ORA_DISK_1: starting datafile copy
input datafile file number=00001 name=/fs-b01-a/databases/orcl1/system-01.dbf
output file name=/fs-b01-a/databases/orcl1/system-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:15
channel ORA_DISK_1: starting datafile copy
input datafile file number=00003 name=/fs-a01-a/databases/orcl1/sysaux-01.dbf
output file name=/fs-a01-a/databases/orcl1/sysaux-01.dbf tag=TAG20110504T072447 RECID=0 STAMP=0
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:15
Finished backup at 04-MAY-11

sql statement: alter system archive log current

contents of Memory Script:
{
   switch clone datafile all;
}
executing Memory Script

datafile 1 switched to datafile copy
input datafile copy RECID=2 STAMP=750238434 file name=/fs-b01-a/databases/orcl1/system-01.dbf
datafile 2 switched to datafile copy
input datafile copy RECID=3 STAMP=750238434 file name=/fs-a01-a/databases/orcl1/undo_t1-01.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=4 STAMP=750238434 file name=/fs-a01-a/databases/orcl1/sysaux-01.dbf
datafile 4 switched to datafile copy
input datafile copy RECID=5 STAMP=750238434 file name=/fs-a01-a/databases/orcl1/administrator-01.dbf
datafile 5 switched to datafile copy
input datafile copy RECID=6 STAMP=750238434 file name=/fs-b01-a/databases/orcl1/administrator_idx-01.dbf
datafile 6 switched to datafile copy
input datafile copy RECID=7 STAMP=750238434 file name=/fs-a01-a/databases/orcl1/replication-01.dbf
datafile 7 switched to datafile copy
input datafile copy RECID=8 STAMP=750238434 file name=/fs-b01-a/databases/orcl1/replication_idx-01.dbf
datafile 8 switched to datafile copy
input datafile copy RECID=9 STAMP=750238434 file name=/fs-a01-a/databases/orcl1/rcvcat-001.dbf
datafile 9 switched to datafile copy
input datafile copy RECID=10 STAMP=750238434 file name=/fs-b01-a/databases/orcl1/rcvcat_idx-001.dbf
datafile 10 switched to datafile copy
input datafile copy RECID=11 STAMP=750238434 file name=/fs-d01-a/databases/orcl1/sysaux-20090310204613.dbf
datafile 11 switched to datafile copy
input datafile copy RECID=12 STAMP=750238434 file name=/fs-d01-a/databases/orcl1/system-20090421171504.dbf
Finished Duplicate Db at 04-MAY-11

RMAN&gt;

This completes active duplication. Your standby is ready now.
Hope this helps !!</pre>
<br />Filed under: <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a> Tagged: <a href='http://avdeo.com/tag/active-database-duplication/'>active database duplication</a>, <a href='http://avdeo.com/tag/active-duplication/'>active duplication</a>, <a href='http://avdeo.com/tag/creating-database-from-existing-database/'>creating database from existing database</a>, <a href='http://avdeo.com/tag/creating-standby/'>creating standby</a>, <a href='http://avdeo.com/tag/creating-standby-without-taking-backup/'>creating standby without taking backup</a>, <a href='http://avdeo.com/tag/oracle-database-11g-2/'>oracle database 11g</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/852/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/852/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/852/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/852/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/852/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/852/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/852/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/852/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=852&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/05/09/creating-standby-database-using-active-duplication-oracle-database-11g/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Avoiding &#8220;no data found&#8221; : Tips</title>
		<link>http://avdeo.com/2011/04/29/avoiding-no-rows-found-tips/</link>
		<comments>http://avdeo.com/2011/04/29/avoiding-no-rows-found-tips/#comments</comments>
		<pubDate>Fri, 29 Apr 2011 14:35:46 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[ORA Errors]]></category>
		<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[avoiding no rows selected]]></category>
		<category><![CDATA[no data found]]></category>
		<category><![CDATA[ORA-01403]]></category>
		<category><![CDATA[plsql]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=848</guid>
		<description><![CDATA[Some time we face issue about no data found depending on selection criteria. And when this happens in PLSQL procedure we get annoying error ORA-01403: No data found and execution stops. One way to get around this error is to add exception block in our PLSQL procedure as shown below EXCEPTION WHEN NO_DATA_FOUND THEN &#60;Take Action&#62; [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=848&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Some time we face issue about no data found depending on selection criteria. And when this happens in PLSQL procedure we get annoying error</p>
<p>ORA-01403: <em>No</em> data found and execution stops.</p>
<p>One way to get around this error is to add exception block in our PLSQL procedure as shown below</p>
<p>EXCEPTION WHEN NO_DATA_FOUND THEN</p>
<p>&lt;Take Action&gt;</p>
<p>But disadvantage of using this approach is that it will not process rest of the code and control will jump to exception block and from there on continue till the end. If we get this error in the middle of FOR loop or WHILE loop, rest of the records will not get processed.</p>
<p>One of the way to deal with this is joining your SQL with dual.</p>
<p>In that case you are sure to get a null value even if the row does not exists.</p>
<p>Example in my case I want to find the memory value and spfile value of one of the parameter in database by querying v$parameter and v$spparameter view.</p>
<p>If I do a simple join as below I am going to get &#8220;no data found&#8221; if these view does not have parameter</p>
<pre>SQL&gt; select a.name, a.value, b.value from v$parameter b, v$spparameter a
  2  where a.name = b.name
  3  and a.name = 'shared_pool_reserved_min_alloc';

no rows selected

SQL&gt;</pre>
<p>But if we join with dual we can get the name of the parameter and a null value in front of that</p>
<pre>SQL&gt; select c.col, a.value, b.value
  2  from v$parameter b, v$spparameter a, (select 'shared_pool_reserved_min_alloc' col from dual) c
  3  where c.col = a.name (+) and c.col = b.name (+);

COL                            VALUE                VALUE
------------------------------ -------------------- --------------------
shared_pool_reserved_min_alloc

SQL&gt;</pre>
<p>This is easier to process.</p>
<p>Hope this helps !!</p>
<br />Filed under: <a href='http://avdeo.com/category/ora-errors/'>ORA Errors</a>, <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a> Tagged: <a href='http://avdeo.com/tag/avoiding-no-rows-selected/'>avoiding no rows selected</a>, <a href='http://avdeo.com/tag/no-data-found/'>no data found</a>, <a href='http://avdeo.com/tag/ora-01403/'>ORA-01403</a>, <a href='http://avdeo.com/tag/plsql/'>plsql</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/848/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/848/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/848/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=848&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/04/29/avoiding-no-rows-found-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>An insight into Oracle Index rebuild</title>
		<link>http://avdeo.com/2011/04/12/an-insight-into-oracle-index-rebuild/</link>
		<comments>http://avdeo.com/2011/04/12/an-insight-into-oracle-index-rebuild/#comments</comments>
		<pubDate>Tue, 12 Apr 2011 05:24:00 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[index monitoring script]]></category>
		<category><![CDATA[index rebuild online]]></category>
		<category><![CDATA[index status]]></category>
		<category><![CDATA[journal table]]></category>
		<category><![CDATA[lock index rebuild]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=842</guid>
		<description><![CDATA[You must have gone through my previous article on Oracle Index rebuild &#8211; 10g Vs 11g &#8211; http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/ Well, there is another nice article written by a friend of mine Sumit Bhatia. He has talked about the actions and events happening while rebuilding an index online in oracle database 11g. Different wait events that we [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=842&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>You must have gone through my previous article on Oracle Index rebuild &#8211; 10g Vs 11g &#8211; <a title="http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/" href="http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/" target="_blank">http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/</a></p>
<p>Well, there is another nice article written by a friend of mine <a title="http://fordba.wordpress.com/about/" href="http://fordba.wordpress.com/about/" target="_blank"><strong>Sumit Bhatia</strong></a>.</p>
<p>He has talked about the actions and events happening while rebuilding an index online in oracle database 11g.</p>
<p>Different wait events that we encounter and to make it more practical he has also build a script which gives you the exact status for your index rebuild.</p>
<p>You can refer to the article at <a title="http://fordba.wordpress.com/2011/04/05/online-ndx-rebuild/" href="http://fordba.wordpress.com/2011/04/05/online-ndx-rebuild/" target="_blank">http://fordba.wordpress.com/2011/04/05/online-ndx-rebuild/</a></p>
<p>You can refer to the script at <a title="http://fordba.wordpress.com/2011/03/30/ndx-progress-sql/" href="http://fordba.wordpress.com/2011/03/30/ndx-progress-sql/" target="_blank">http://fordba.wordpress.com/2011/03/30/ndx-progress-sql/</a></p>
<p>Just to mention, this script is by no means a complete script and enhancements can be underway. Also this script should not be used in production. If you want to use in production, you can do it at your own risk.</p>
<p>Hope this helps !!</p>
<br />Filed under: <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a> Tagged: <a href='http://avdeo.com/tag/index-monitoring-script/'>index monitoring script</a>, <a href='http://avdeo.com/tag/index-rebuild-online/'>index rebuild online</a>, <a href='http://avdeo.com/tag/index-status/'>index status</a>, <a href='http://avdeo.com/tag/journal-table/'>journal table</a>, <a href='http://avdeo.com/tag/lock-index-rebuild/'>lock index rebuild</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/842/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/842/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/842/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/842/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/842/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/842/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/842/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/842/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=842&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/04/12/an-insight-into-oracle-index-rebuild/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Exchange Partition in Oracle</title>
		<link>http://avdeo.com/2011/03/30/exchange-partition-in-oracle/</link>
		<comments>http://avdeo.com/2011/03/30/exchange-partition-in-oracle/#comments</comments>
		<pubDate>Wed, 30 Mar 2011 20:04:10 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Oracle Database 10g]]></category>
		<category><![CDATA[Oracle Database 9i]]></category>
		<category><![CDATA[exchange partition]]></category>
		<category><![CDATA[non-partition to partition]]></category>
		<category><![CDATA[partition table]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=837</guid>
		<description><![CDATA[Some times we faced a need to convert our existing table from non-partition table to a partition table or vice-versa. Or moving a partition of one partition table to another partition. Or make one of the table as a partition of some partition table. Or make a partition of one of the partition table as [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=837&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Some times we faced a need to convert our existing table from non-partition table to a partition table or vice-versa. Or moving a partition of one partition table to another partition. Or make one of the table as a partition of some partition table. Or make a partition of one of the partition table as a separate table.</p>
<p>To deal with this kind of situation, oracle has introduced exchange partition functionality long time a go (I guess from 8i onwards).<br />
We will see a simple example of how to convert a simple non-partition table to a partition table.</p>
<p>1) Create a table, create index on table and gather stats on table and index</p>
<p><pre class="brush: sql;">

ORCL1&gt;create table t as select * from dba_objects;

Table created.

ORCL1&gt;create index t_idx on t(owner, object_name);

Index created.

ORCL1&gt;exec dbms_stats.gather_table_stats('ADVAITD_DBA','T',cascade=&gt;true);

PL/SQL procedure successfully completed.

ORCL1&gt;select count(1) from t;

 COUNT(1)
----------
 14966

</pre></p>
<p>2) Create partition table with basic partition</p>
<p><pre class="brush: sql;">

ORCL1&gt;create table pt (
 2  OWNER           VARCHAR2(30),
 3  OBJECT_NAME     VARCHAR2(128),
 4  SUBOBJECT_NAME  VARCHAR2(30),
 5  OBJECT_ID       NUMBER,
 6  DATA_OBJECT_ID  NUMBER,
 7  OBJECT_TYPE     VARCHAR2(19),
 8  CREATED         DATE,
 9  LAST_DDL_TIME   DATE,
 10  TIMESTAMP       VARCHAR2(19),
 11  STATUS          VARCHAR2(7),
 12  TEMPORARY       VARCHAR2(1),
 13  GENERATED       VARCHAR2(1),
 14  SECONDARY       VARCHAR2(1),
 15  NAMESPACE       NUMBER,
EDITION_NAME    VARCHAR2(30)
 16   17  )
 18  partition by range (CREATED)
 19  (PARTITION PT_2011 VALUES less than (MAXVALUE));

Table created.

ORCL1&gt;select count(1) from pt;

 COUNT(1)
----------
 0

</pre></p>
<p>3) Exchange the partition with table</p>
<p><pre class="brush: sql;">

ORCL1&gt;alter table pt exchange partition PT_2011 with table T without validation;

Table altered.

ORCL1&gt;select count(1) from pt;

 COUNT(1)
----------
 14966

ORCL1&gt;select count(1) from t;

 COUNT(1)
----------
 0

</pre></p>
<p>4) Split the partition and check</p>
<pre>ALTER TABLE pt
SPLIT PARTITION PT_2011 AT (TO_DATE('31-DEC-2006', 'DD-MON-YYYY'))
INTO (PARTITION PT_2006,
 PARTITION PT_2011)</pre>
<p>Analyze the table</p>
<pre>exec dbms_stats.gather_table_stats('ADVAITD_DBA','PT',cascade=&gt;true);</pre>
<p>Check the number of rows in each partition</p>
<p><pre class="brush: sql;">

ORCL1&gt;select TABLE_NAME, PARTITION_NAME, HIGH_VALUE, NUM_ROWS from dba_tab_partitions where TABLE_NAME = 'PT';

TABLE_NAME                     PARTITION_NAME                 HIGH_VALUE                       NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ----------
PT                             PT_2006                        TO_DATE(' 2006-12-31 00:00:00'       8919
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2011                        MAXVALUE                             6047

</pre></p>
<p>Like that split again and check the records</p>
<pre>ALTER TABLE pt
SPLIT PARTITION PT_2011 AT (TO_DATE('31-DEC-2007', 'DD-MON-YYYY'))
INTO (PARTITION PT_2007,
 PARTITION PT_2011)

exec dbms_stats.gather_table_stats('ADVAITD_DBA','PT',cascade=&gt;true);

ORCL1&gt;select TABLE_NAME, PARTITION_NAME, HIGH_VALUE, NUM_ROWS from dba_tab_partitions where TABLE_NAME = 'PT';

TABLE_NAME                     PARTITION_NAME                 HIGH_VALUE                       NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ----------
PT                             PT_2006                        TO_DATE(' 2006-12-31 00:00:00'       8919
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2007                        TO_DATE(' 2007-12-31 00:00:00'        110
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2011                        MAXVALUE                             5937</pre>
<p>Do for rest of the partitions</p>
<p><pre class="brush: sql;">

ALTER TABLE pt
SPLIT PARTITION PT_2011 AT (TO_DATE('31-DEC-2008', 'DD-MON-YYYY'))
INTO (PARTITION PT_2008,
 PARTITION PT_2011)

ALTER TABLE pt
SPLIT PARTITION PT_2011 AT (TO_DATE('31-DEC-2010', 'DD-MON-YYYY'))
INTO (PARTITION PT_2010,
 PARTITION PT_2011)

exec dbms_stats.gather_table_stats('ADVAITD_DBA','PT',cascade=&gt;true);

ORCL1&gt;select TABLE_NAME, PARTITION_NAME, HIGH_VALUE, NUM_ROWS from dba_tab_partitions where TABLE_NAME = 'PT';

TABLE_NAME                     PARTITION_NAME                 HIGH_VALUE                       NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ----------
PT                             PT_2006                        TO_DATE(' 2006-12-31 00:00:00'       8919
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2007                        TO_DATE(' 2007-12-31 00:00:00'        110
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2008                        TO_DATE(' 2008-12-31 00:00:00'        250
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

TABLE_NAME                     PARTITION_NAME                 HIGH_VALUE                       NUM_ROWS
------------------------------ ------------------------------ ------------------------------ ----------

PT                             PT_2009                        TO_DATE(' 2009-12-31 00:00:00'        312
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2010                        TO_DATE(' 2010-12-31 00:00:00'        163
 , 'SYYYY-MM-DD HH24:MI:SS', 'N
 LS_CALENDAR=GREGORIA

PT                             PT_2011                        MAXVALUE                             5212

6 rows selected.

</pre></p>
<p>Regarding the index, we can create the similar index on partition table as well. We will create it a local index</p>
<pre>ORCL1&gt;create index PT_IDX on PT(owner, object_name) local;
Index created.
ORCL1&gt;</pre>
<p>This step can be done before as well, but doesnt matter.</p>
<p>Now lets verify the results</p>
<p><pre class="brush: sql;">

ORCL1&gt;select count(1) from dba_objects where created &lt; to_date('2006-12-31','YYYY-MM-DD');

 COUNT(1)
----------
 8919

ORCL1&gt;select count(1) from dba_objects where created &lt; to_date('2007-12-31','YYYY-MM-DD') and created &gt; to_date('2006-12-31','YYYY-MM-DD');

 COUNT(1)
----------
 110

ORCL1&gt;select count(1) from dba_objects where created &lt; to_date('2008-12-31','YYYY-MM-DD') and created &gt; to_date('2007-12-31','YYYY-MM-DD');

 COUNT(1)
----------
 250

ORCL1&gt;select count(1) from dba_objects where created &lt; to_date('2009-12-31','YYYY-MM-DD') and created &gt; to_date('2008-12-31','YYYY-MM-DD');

 COUNT(1)
----------
 312

ORCL1&gt;select count(1) from dba_objects where created &lt; to_date('2010-12-31','YYYY-MM-DD') and created &gt; to_date('2009-12-31','YYYY-MM-DD');

 COUNT(1)
----------
 163

ORCL1&gt;select count(1) from dba_objects where created &lt; to_date('2011-12-31','YYYY-MM-DD') and created &gt; to_date('2010-12-31','YYYY-MM-DD');

 COUNT(1)
----------
 5220

RCATLTN1&gt;
</pre></p>
<p>So this is how we can convert a simple non-partition table to a partition table.<br />
Don&#8217;t forgot to gather status again after creating all partitions and indexes.</p>
<p>Hope this helps !!</p>
<br />Filed under: <a href='http://avdeo.com/category/oracle-database-10g/'>Oracle Database 10g</a>, <a href='http://avdeo.com/category/oracle-database-9i/'>Oracle Database 9i</a> Tagged: <a href='http://avdeo.com/tag/exchange-partition/'>exchange partition</a>, <a href='http://avdeo.com/tag/non-partition-to-partition/'>non-partition to partition</a>, <a href='http://avdeo.com/tag/partition-table/'>partition table</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/837/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/837/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/837/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/837/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/837/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/837/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/837/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/837/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=837&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/03/30/exchange-partition-in-oracle/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Virual Index and Invisible Index</title>
		<link>http://avdeo.com/2011/03/23/virual-index-and-invisible-index/</link>
		<comments>http://avdeo.com/2011/03/23/virual-index-and-invisible-index/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 06:07:22 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Oracle Database 10g]]></category>
		<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[Oracle Database 9i]]></category>
		<category><![CDATA[invisible index]]></category>
		<category><![CDATA[virtual index]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=741</guid>
		<description><![CDATA[Oracle has come up with a feature called virtual index in oracle 9i. This feature allow us to test an index on a table without actually adding an index on the table. The table will be visible only in our session and will be used by our queries only (if optimizer decide it to use). [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=741&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Oracle has come up with a feature called virtual index in oracle 9i. This feature allow us to test an index on a table without actually adding an index on the table. The table will be visible only in our session and will be used by our queries only (if optimizer decide it to use). So basically the index will be visible to optimizer only in our sessions. Optimizer running query in other sessions won&#8217;t be able to see this index.</p>
<p><span style="text-decoration:underline;"><strong>Virtual Index in Oracle 9i</strong></span></p>
<p>Utility of using virtual index is that, suppose we have a table having huge number of rows and it is getting joined with other tables. If we see that optimizer is creating a plan which is costly and SQL tuning advisor suggest us to create an index on a column, then in case of production database we cannot simply create an index and test the changes. We need to make sure that creating that index wont have any negative impact on the execution plan of other queries running in this database.</p>
<p>So there is where we can use virtual index. Here is how virtual index works.</p>
<p>1) Creating a table</p>
<pre>SQL&gt; create table test as select * from dba_objects;

Table created.</pre>
<p>2) Try selecting a value from test table</p>
<pre>SQL&gt; select * from test where object_name = 'STANDARD';

Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| TEST |
----------------------------------</pre>
<p>3) Create a virtual Index on test table</p>
<pre>SQL&gt; create index test_idx_1 on test(object_name) nosegment;

Index created.</pre>
<p>In order to create a virtual index, we need to give NOSEGMENT at the end of the create index statement. This will just create a index on the object_name column of test table. But it will not create an index segment in database.</p>
<p>You can check this by querying dba_objects and dba_indexes tables.</p>
<pre>SQL&gt; select index_name from dba_indexes where table_name = 'TEST' and index_name = 'TEST_IDX_1';

no rows selected
SQL&gt; col OBJECT_NAME format a30;
SQL&gt; select object_name, object_type from dba_objects where object_name = 'TEST_IDX_1';

OBJECT_NAME                    OBJECT_TYPE
------------------------------ -------------------
TEST_IDX_1                     INDEX</pre>
<p>So, object exists in database, but we dont have segment for the same.</p>
<p>Now if you try to run the same select command on test table, still optimizer will NOT use virtual index.</p>
<pre>SQL&gt; select * from test where object_name = 'STANDARD';
Execution Plan
----------------------------------------------------------
Plan hash value: 1357081020

----------------------------------
| Id  | Operation         | Name |
----------------------------------
|   0 | SELECT STATEMENT  |      |
|*  1 |  TABLE ACCESS FULL| TEST |
----------------------------------</pre>
<p>In order for optimizer to use virtual index, you need to set a parameter called _USE_NOSEGMENT_INDEXES in your session</p>
<pre>SQL&gt; alter session set "_USE_NOSEGMENT_INDEXES" = true;

Session altered.</pre>
<p>Once you set this hidden parameter, optimizer will start using the virtual index you created on this table</p>
<pre>SQL&gt; select * from test where object_name = 'STANDARD';

Execution Plan
----------------------------------------------------------
Plan hash value: 1221747299

------------------------------------------------------------------------------------------
| Id  | Operation                   | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |            |     2 |   354 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TEST       |     2 |   354 |     1   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | TEST_IDX_1 |    46 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------</pre>
<p>If you run this query from some other session, it wont use virtual index.</p>
<p>you can analyze virtual indexes</p>
<pre>SQL&gt; analyze index TEST_IDX_1 compute statistics;

Index analyzed.</pre>
<p>You CANNOT rebuild a virtual index</p>
<pre>SQL&gt; alter index TEST_IDX_1 rebuild;
alter index TEST_IDX_1 rebuild
*
ERROR at line 1:
ORA-08114: can not alter a fake index</pre>
<p>Finally, if the index doesn&#8217;t seem to satisfy your requirement, then you can drop the virtual index.</p>
<pre>SQL&gt; drop index TEST_IDX_1;

Index dropped.</pre>
<p><span style="text-decoration:underline;"><strong>Invisible Index in 11g</strong></span></p>
<p>We have a similar concept in Oracle database 11g called invisible index.</p>
<p>In case of invisible index, we can check if creating a new index is actually going to improve the performance or not. This index will not be visible to any other session and it will not be used by any other existing query run on same table.</p>
<pre>SQL&gt;drop table t;

Table dropped.

SQL&gt;create table t as select * from dba_objects;

Table created.

SQL&gt;create index t_ind1 on t(object_name) invisible;

Index created.</pre>
<p>You can also make existing index as invisible using alter index command. You can make existing invisible index as visible. As soon as you make index visible, your existing queries will start using new index.</p>
<pre>TDCLTN1&gt;alter index t_ind1 visible;
TDCLTN1&gt;alter index t_ind1 invisible;</pre>
<p>We have a new column in USER_INDEXES called VISIBILITY. This tells whether an index is visible or not.</p>
<pre>SQL&gt;select index_name,VISIBILITY from user_indexes where index_name='T_IND1';

INDEX_NAME                     VISIBILIT
------------------------------ ---------
T_IND1                         INVISIBLE</pre>
<p>So how does INVISIBLE index works ?</p>
<p>Now that we have created an INVISIBLE index, lets try to run a query on new table T and see if it uses the index.</p>
<pre>SQL&gt;explain plan for
 2  select * from t where object_name='STANDARD';

Explained.

SQL&gt;select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1601196873

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

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

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------

 1 - filter("OBJECT_NAME"='STANDARD')</pre>
<p>So we can see its doing a full table scan.</p>
<p>In order to use the invisible index, we have a new parameter introduced in 11g &#8211; <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/initparams163.htm#REFRN10301">OPTIMIZER_USE_INVISIBLE_INDEXES</a></p>
<p>This parameter can be set to either TRUE or FALSE</p>
<p>If set to true, we are asking optimizer to use the invisible index if it can make a better plan using that.</p>
<p>Lets try to set this parameter to TRUE and run the same query.</p>
<pre>SQL&gt;select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------------------
| Id  | Operation                   | Name   | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |        |     2 |   202 |     4   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| T      |     2 |   202 |     4   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | T_IND1 |     2 |       |     3   (0)| 00:00:01 |
-------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------
1 - filter("OBJECT_NAME"='STANDARD')</pre>
<p>Now it has used the index and the cost of the query also reduced.</p>
<p>If the index seems to make positive impact on the other query as well, then you can make this index as visible.</p>
<p>Note that if the index is INVISIBLE, then optimizer will ignore the index and 10053 trace will show index as &#8220;UNUSABLE&#8221;</p>
<p><span style="text-decoration:underline;"><strong>Difference:</strong></span></p>
<p>So based on above examples, we can see that the difference is</p>
<p>- In case of virtual index, we dont actually create the index, its just the place holder. In case of invisible index we actually create the index</p>
<p>- In case of virtual index, we can check if the index is getting used or not using explain plan and performance of the query can be mentioned statistically by explain plan. In case of invisible index, we can actually run the query and check the performance benefit.</p>
<p>- We cannot make existing index as virtual, unless we have to drop it and create a no_segment index. We can make any index invisible.</p>
<p>Hope this helps !!</p>
<br />Filed under: <a href='http://avdeo.com/category/oracle-database-10g/'>Oracle Database 10g</a>, <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a>, <a href='http://avdeo.com/category/oracle-database-9i/'>Oracle Database 9i</a> Tagged: <a href='http://avdeo.com/tag/invisible-index/'>invisible index</a>, <a href='http://avdeo.com/tag/virtual-index/'>virtual index</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/741/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/741/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/741/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=741&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/03/23/virual-index-and-invisible-index/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
		<item>
		<title>Oracle Index rebuild online &#8211; 10g Vs 11g</title>
		<link>http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/</link>
		<comments>http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/#comments</comments>
		<pubDate>Thu, 17 Mar 2011 07:34:04 +0000</pubDate>
		<dc:creator>advait</dc:creator>
				<category><![CDATA[Oracle Database 10g]]></category>
		<category><![CDATA[Oracle Database 11g]]></category>
		<category><![CDATA[11g index rebuild]]></category>
		<category><![CDATA[journal table]]></category>
		<category><![CDATA[online index rebuild]]></category>

		<guid isPermaLink="false">http://avdeo.com/?p=832</guid>
		<description><![CDATA[An index is basically used for faster access to tables. Over a period of time the index gets fragmented because of several DMLs running on table. When the index gets fragmented, data inside the index is scattered, rows / block reduces, index consumes more space and scanning of index takes more time and more blocks [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=832&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>An index is basically used for faster access to tables. Over a period of time the index gets fragmented because of several DMLs running on table.<br />
When the index gets fragmented, data inside the index is scattered, rows / block reduces, index consumes more space and scanning of index takes more time and more blocks for same set of queries.<br />
To talk in index terminology, we will have a single root block, but as fragmentation increases there will be more number of branch blocks and more leaf blocks. Also the height of index will increase.</p>
<p>To fix the above issue, we go for index rebuild. During index rebuild, the data inside the index is reorganized and compressed to fit in minimum number of blocks, height of the index is reduced to minimum possible level and performance of queries will increase.<br />
Your search becomes faster and your query will read less number of blocks.</p>
<p>There are 2 methods to rebuild the index.</p>
<p>1) Offline index rebuild &#8211; alter index &lt;index name&gt; rebuild;<br />
2) Online index rebuild  &#8211; alter index &lt;index name&gt; rebuild online;</p>
<p>With offline index rebuild, table and index is locked in exclusive mode preventing any translations on the table. This is most intrusive method and is used rarely in production unless we know for sure that modules are not going to access the table and we have complete downtime.</p>
<p>With online index rebuild, transactions can still access the table and index. Only for very less amount of time the lock is acquired on the table (by index rebuild operation). For rest of the time table and index is available for transactions.<br />
However there is a difference in a way this internal online rebuild mechanism works in 10g and 11g. With 11g things are refined further to minimize the impact.</p>
<p>I will first explain the 10g method of rebuilding the index, after that will see the behavior in 11g</p>
<p><span style="text-decoration:underline;"><strong>10g behaviour:</strong></span></p>
<p>The way online index build (OIB) works is by creating an IOT journal table to keep track of changes while the OIB is in progress and merge all the changes from journal table to complete index build operation.</p>
<p>If I have a table with the structure of (A NUMBER, B NUMBER, C CHAR(100), D NUMBER) and to create index on (A, B, C) column, Oracle would create journal table like:</p>
<p>create table &#8220;ORACLE&#8221;.&#8221;SYS_JOURNAL_18155&#8243; (C0 NUMBER, C1 NUMBER, C2 VARCHAR2(100), opcode char(1), partno number, rid rowid, primary key( C0, C1, C2 , rid )) organization index;</p>
<p>Before 11g, OIB will get in the DML queue to lock the table exclusively while preventing the new DML&#8217;s to go through, once all the active transactions (ones which were initiated before the OIB) are completed, OIB will create the journal IOT table and release the exclusive table lock (it&#8217;ll still keep the share lock on the table to prevent any other DDL&#8217;s) for DML&#8217;s to continue.</p>
<p>As part of journal table creation, Oracle would create an internal trigger on the primary table to record all the changes to the journal table. Along with using all the index columns, journal table will add &#8220;ROWID&#8221; to that list to make it as primary key.</p>
<p>&#8220;OPCODE&#8221; column represents the type of operation like &#8220;I&#8221; for Insert and &#8220;D&#8221; for Delete.<br />
&#8220;PARTNO&#8221; column represents partition number of the underlying table.</p>
<p>Among all the changes to a given row for any of the index key columns, only the most recent change for that record is visible in the journal table. Any update operation of index key columns would be converted to &#8220;DELETE&#8221; and &#8220;INSERT&#8221; in the journal table.</p>
<p>While rest of the user sessions populate journal table with the ongoing changes for index key columns, OIB session would be reading the table in consistent mode (as of the time journal table is created) to create the index followed by the final merge operation.</p>
<p>During the merge process, Oracle will read the journal table (IOT) leaf blocks from left to right to merge those changes with the index being built. As the journal table leaf block changes are applied, once a leaf block is fully consumed, it&#8217;s reference will be deleted from the branch block.</p>
<p>This process will continue until all leaf blocks are consumed and when it comes to the last leaf block, Oracle would stop all the DML&#8217;s again to do the final merge and drop the journal table before releasing the mode 6 exclsuive table lock.</p>
<p>As each leaf block is consumed, Oracle would mark each entry as deleted. If more DML&#8217;s happen while Oracle is doing the merge, it&#8217;ll do one more pass of walking through the leaf blocks, this process continues until the merge process is all done.</p>
<p>If there is any long running DML before issuing the OIB, Oracle would wait on the long running transaction and it will prevent upcoming DML&#8217;s also. This is one of the major problems with OIB. Same thing can happen when it is doing the final merge.</p>
<p>So in the above process lock is acquired 2 times, one during the start of index creation when journal table is created online index rebuild process needs to be take exclusive lock on table to prevent DMLs from changing data. Once journal table is created online index rebuild process will release DML lock and hold a shared lock. Any DMLs happening after this will have entry made into journal table.<br />
Again at the end of the process online index rebuild process will try to take exclusive lock to merge the last block of journal table into the main index.</p>
<p><span style="text-decoration:underline;">Following example demonstrate the same:</span></p>
<p>Create test table and insert huge number of rows</p>
<p><pre class="brush: sql;">&lt;/pre&gt;
SQL&gt;create table test as select * from dba_objects;

Table created.

SQL&gt;insert into test select * from test;

29493 rows created.

SQL&gt;/

58986 rows created.

</pre></p>
<p>Like this add more rows till it becomes big</p>
<p>Check the size of table</p>
<p><pre class="brush: sql;">

SQL&gt;select sum(bytes)/1024/1024/1024 from dba_segments where segment_name = 'TEST';

SUM(BYTES)/1024/1024/1024
-------------------------
 .430053711

Create index on the table

SQL&gt;create index I1 on test(OBJECT_NAME);

Index created.

Check the size of index.

SQL&gt;select sum(bytes)/1024/1024/1024 from dba_segments where segment_name = 'I1';

SUM(BYTES)/1024/1024/1024
-------------------------
 .129272461

</pre></p>
<p>Now from the session 1, try inserting a record in the TEST table</p>
<p>Session 1 SID: 3204<br />
SQL Text :</p>
<pre>SQL&gt;insert into test (owner, object_name) values ('AVDEO','NEW_TEST');
1 row created.
SQL&gt;</pre>
<p>From session 2, try rebuilding the index online</p>
<p>Session 2 SID: 3046<br />
SQL text :</p>
<p>alter index I1 rebuild online</p>
<p>From session 3, run another DML command.</p>
<p>Session 3 SID: 3827<br />
SQL Text:</p>
<p>update test set OWNER = &#8216;DEO2&#8242; where OWNER = &#8216;DEO&#8217;</p>
<p>If we check v$lock table we can see session 2 (online index rebuild) is waiting on session 1 (insert). So unless insert completes, session 2 doing online index rebuild will not get a exclusive lock.</p>
<p><pre class="brush: sql;">

SQL&gt;select
 2      l.SID oracle_id,
 3      decode(TYPE,
 4          'MR', 'Media Recovery',
 5          'RT', 'Redo Thread',
 6          'UN', 'User Name',
 7          'TX', 'Transaction',
 8          'TM', 'DML',
 9          'UL', 'PL/SQL User Lock',
 10          'DX', 'Distributed Xaction',
 11          'CF', 'Control File',
 12          'IS', 'Instance State',
 13          'FS', 'File Set',
 14          'IR', 'Instance Recovery',
 15          'ST', 'Disk Space Transaction',
 16          'TS', 'Temp Segment',
 17          'IV', 'Library Cache Invalidation',
 18          'LS', 'Log Start or Switch',
 19          'RW', 'Row Wait',
 20          'SQ', 'Sequence Number',
 21          'TE', 'Extend Table',
 22          'TT', 'Temp Table', type) lock_type,
 23      decode(LMODE,
 24          0, 'None',
 25          1, 'Null',
 26          2, 'Row-S (SS)',
 27          3, 'Row-X (SX)',
 28          4, 'Share',
 29          5, 'S/Row-X (SSX)',
 30          6, 'Exclusive', lmode) lock_held,
 31      decode(REQUEST,
 32          0, 'None',
 33          1, 'Null',
 34          2, 'Row-S (SS)',
 35          3, 'Row-X (SX)',
 36          4, 'Share',
 37          5, 'S/Row-X (SSX)',
 38          6, 'Exclusive', request) lock_requested,
 39      decode(BLOCK,
 40          0, 'Not Blocking',
 41          1, 'Blocking',
 42          2, 'Global', block) status,
 43      OBJECT_NAME
 44  from    v$locked_object lo,
 45      dba_objects do,
 46      v$lock l
 47  where     lo.OBJECT_ID = do.OBJECT_ID
 48  AND     l.SID = lo.SESSION_ID
 49  /

 ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 3204 DML                        Row-X (SX)                               None                                     Blocking             TEST
 3204 Transaction                Exclusive                                None                                     Not Blocking         TEST
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DML                        Share                                    None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DML                        Row-S (SS)                               Share                                    Not Blocking         SYS_JOURNAL_1664589
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         TEST
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         TEST
 3075 DML                        Share                                    None                                     Not Blocking         TEST
 3075 DML                        Row-S (SS)                               Share                                    Not Blocking         TEST
 3900 DML                        None                                     Row-X (SX)                               Not Blocking         TEST

</pre></p>
<p>From the above output we can see that first session is 3204 which is running insert.<br />
Session 2 is 3075 which is running index rebuild and is waiting for &#8220;DML share&#8221; lock<br />
session 3 is 3900 running update DML and waiting for &#8220;DML Row-X&#8221; lock</p>
<p>If we see which session is blocking what we see below rows</p>
<p><pre class="brush: sql;">

Logn Ora    SQL/Prev                     OS                                                   Call
&gt;&lt;    Sid-Ser-S Time User   Hash       Module            User   Svr-Pgm    Machine      HR Resource           Elap Ctim Locked Object
--------------- ---- ------ ---------- ----------------- ------ ---------- ------------ -- ------------------ ---- ---- --------------------
&gt;  3204,23884-I 0953 ADVAIT 0          SQL*Plus          advait 7924-orac  db-fc-admin- 3  TM:1664558-0       448s 448s 1664558
 &lt; 3075,20427-A 0959 ADVAIT 3645454058 SQL*Plus          advait 15432-orac db-fc-admin-  4                    433s 432s 1664558
 &lt; 3900,30565-A 0959 ADVAIT 4227999514 SQL*Plus          advait 16004-orac db-fc-admin-  3                    408s 408s 1664558

</pre></p>
<p>Above output is generated by my custom scripts.</p>
<p>It says that 3204 is parent session and 3204 and 3900 is waiting on 3204.</p>
<p>In case of 10g if we commit session 1 (sid 3204 running insert), it will allow online index rebuild to continue and get the lock.<br />
Session 3 will still continue to wait until session 2 running online index rebuild releases the lock.</p>
<p>After some time session 2 will start with index rebuild, it will take lock for very short period of time and releases the lock.<br />
Session 3 (update DML) will aquire the lock after session 2 (index rebuild) releases the lock.</p>
<p>Session 3 completed while session 2 (index rebuild) does table scan.</p>
<pre>SQL&gt;update test set OWNER = 'DEO2' where OWNER = 'DEO'
 2  ;
1 rows updated.
SQL&gt;</pre>
<p>Now after session 3 DML completes, we didnt commit session 3. We are waiting for session 2 to complete now.</p>
<p>We can check v$session_longops to see current operation for index rebuild</p>
<p><pre class="brush: sql;">

SQL&gt;select sid, OPNAME, SOFAR, TOTALWORK, TIME_REMAINING, ELAPSED_SECONDS from v$session_longops where sid = 3075;

 SID OPNAME                                                                SOFAR  TOTALWORK TIME_REMAINING ELAPSED_SECONDS
------ ---------------------------------------------------------------- ---------- ---------- -------------- ---------------
 3075 Sort Output                                                           25011      25011              0              15
 3075 Table Scan                                                            56036      56036              0              61

2 rows selected.

</pre></p>
<p>So we can see that v$session_longops that table scan for index rebuild completed. But still the session 2 for index rebuild is hanging.</p>
<p>If we run above query to see the locks it gives below output</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DML                        Share                                    None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DML                        Row-S (SS)                               Share                                    Not Blocking         SYS_JOURNAL_1664589
 3075 Temp Segment               Exclusive                                None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 Transaction                Exclusive                                None                                     Not Blocking         SYS_JOURNAL_1664589
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         TEST
 3075 DL                         Row-X (SX)                               None                                     Not Blocking         TEST
 3075 DML                        Share                                    None                                     Not Blocking         TEST
 3075 DML                        Row-S (SS)                               Share                                    Not Blocking         TEST
 3075 Temp Segment               Exclusive                                None                                     Not Blocking         TEST
 3075 Transaction                Exclusive                                None                                     Not Blocking         TEST
 3900 DML                        Row-X (SX)                               None                                     Blocking             TEST

13 rows selected.

&amp;nbsp;

</pre></p>
<p>So sid 3900 is the blocking session. This is session 3 which has run update query but havent commited.<br />
So online index rebuild is waiting to acquire lock second time at the end. This is the time when it has to do the merging.</p>
<p>So after we commit session 3, session 2 doing online index rebuild will acquire the lock and will complete.</p>
<p><span style="text-decoration:underline;"><strong>11g behaviour: </strong></span></p>
<p>With 11g, significant changes were introduced to address all these problems.</p>
<p>Oracle will still wait for long running transactions to complete before starting the OIB process, but it will not block the upcoming DML&#8217;s. Oracle will not use exclusive table lock (mode 6) for OIB, which will eliminate any DML hang situations.</p>
<p>As soon as OIB process is initiated, Oracle will create IOT journal table and use internal trigger on the underlying table to keep track of the changes.</p>
<p>Once the journal table is created and the long running transactions are completed, Oracle will create the index by reading the table blocks in &#8220;CURRENT&#8221; mode, which means any committed changes in a block happened before the current SCN are read instead of the old way of accessing the blocks as of journal table creation time. This will virtually eliminate chance of running into rollback segment too small errors.</p>
<p>Oracle will recreate the internal trigger to directly modify the target index structure once the index build is completed (but the merge job is still pending). This means all user sessions will now directly update the target index instead of updating the journal table. Any change coming through would first be checked in the journal table before consolidating the change for the target index (this is best explanied with the example below).</p>
<p>Record &#8220;A&#8221; was inserted with rowid &#8220;RID&#8221; before the merge phase and hence it is tracked in the journal table.<br />
Record &#8220;A&#8221; was deleted during the merge phase. Now the user session will read the journal table by record &#8220;A&#8221; with rowid &#8220;RID&#8221; and apply that change to the target index before deleteing the same record. It will also mark that record as consumed (i.e. deleted) in the IOT journal table leaf block.</p>
<p>While the user sessions continue to update the target index with the ongoing changes, OIB session will do the merge of journal table changes into the final index, as there will not be any ongoing DML changes being tracked in the journal table, this process will complete faster than before (i.e. pre 11g).</p>
<p><span style="text-decoration:underline;">Lets take an example. In case of 11g we have MYTAB table and MYTAB_IDX index</span></p>
<p><pre class="brush: sql;">

SQL&gt;select sum(bytes)/1024/1024 from dba_segments where segment_name = 'MYTAB';

SUM(BYTES)/1024/1024
--------------------
 406.5

SQL&gt;select sum(bytes)/1024/1024 from dba_segments where segment_name = 'MYTAB_IDX';

SUM(BYTES)/1024/1024
--------------------
 152.5

</pre></p>
<p>In this case also do the following activity</p>
<p>From session 1 run a DML (insert statement) &#8211; SID 2213<br />
From session 2 run index rebuild online command &#8211; SID 2222<br />
From session 3 run a DML (update statement) &#8211; SID 2177</p>
<p>The current status in v$lock shows following</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 2177 AE                         Share                                    None                                     Not Blocking         MYTAB
 2177 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2177 Transaction                Exclusive                                None                                     Not Blocking         MYTAB
 2213 AE                         Share                                    None                                     Not Blocking         MYTAB
 2213 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2213 Transaction                Exclusive                                None                                     Blocking             MYTAB
 2222 AE                         Share                                    None                                     Not Blocking         MYTAB
 2222 OD                         Exclusive                                None                                     Not Blocking         MYTAB
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         MYTAB
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         MYTAB
 2222 OD                         Share                                    None                                     Not Blocking         MYTAB
 2222 Transaction                None                                     Share                                    Not Blocking         MYTAB
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         MYTAB
 2222 DML                        Share                                    None                                     Not Blocking         MYTAB
 2222 Transaction                Exclusive                                None                                     Not Blocking         MYTAB
 2222 AE                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                None                                     Share                                    Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701

</pre></p>
<p>Now if you compare it with 10g we see significant differences.</p>
<p>1) We see lot of extra locks in 11g compared to 10g<br />
2) and the most important differences is that in case of 10g if you see last 2 rows in first output of v$lock we see</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 3075 DML                        Row-S (SS)                               Share                                    Not Blocking         TEST
 3900 DML                        None                                     Row-X (SX)                               Not Blocking         TEST

</pre></p>
<p>and same in 11g is</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 2177 AE                         Share                                    None                                     Not Blocking         MYTAB
 2177 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2177 Transaction                Exclusive                                None                                     Not Blocking         MYTAB
 2213 AE                         Share                                    None                                     Not Blocking         MYTAB
 2213 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2213 Transaction                Exclusive                                None                                     Blocking             MYTAB
 .
 .
 2222 Transaction                None                                     Share                                    Not Blocking         MYTAB

</pre></p>
<p>In case of 10g if you see 3075 is the one which is doing an index rebuild and is waiting on initial sid 3204. Also 3rd session (3900) running DML is waiting for &#8220;Row-X (SX)&#8221; lock.<br />
In case of 11g if you see 2222 is the one which is doing an index rebuild and is waiting on initial sid 2213. Also 3rd session (2177) running DML already got &#8220;Row-X (SX)&#8221; lock and is not waiting for anything.</p>
<p>So in case of 11g if index rebuild is waiting for initial lock to acquire, it does not block incomming DMLs.</p>
<p>After I commit 1st session I see that none of the session is now blocking index rebuild operation and so it can acquire initial lock</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 2177 AE                         Share                                    None                                     Not Blocking         MYTAB
 2177 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2177 Transaction                Exclusive                                None                                     Not Blocking         MYTAB
 2222 AE                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 AE                         Share                                    None                                     Not Blocking         MYTAB
 2222 OD                         Exclusive                                None                                     Not Blocking         MYTAB
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         MYTAB
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         MYTAB
 2222 OD                         Share                                    None                                     Not Blocking         MYTAB
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         MYTAB
 2222 DML                        Share                                    None                                     Not Blocking         MYTAB
 2222 Transaction                Exclusive                                None                                     Not Blocking         MYTAB

</pre></p>
<p>My session 3 is already complete and I commited that session now. session 3 had no dependency on any session.</p>
<p>After index rebuild start (its doing table scan), I run one more DML from session 3, but I dont commit. In this case index rebuild will hang again at the end waiting for exclusive lock on table.<br />
Unless session 3 gives the lock index rebuild cannot proceed.</p>
<p>Important change here between 10g and 11g is that if we start 4th session while index rebuild waits for 2nd time for lock and if I commit session 3, in case of 10g index rebuild will get precedence and it will acquire lock blocking session 4.<br />
In case of 11g session 4 will get presedence and will acquire lock for DML, where as index rebuild will wait further until all DML sessions are complete and lock is available for it to acquire. So online index rebuild will prioritize all other sessions before him to acquire locks.</p>
<p>From v$session_longops we can see that tablescan operation completed</p>
<p><pre class="brush: sql;">

SQL&gt;select sid, OPNAME, SOFAR, TOTALWORK, TIME_REMAINING, ELAPSED_SECONDS from v$session_longops where sid = 2222 and opname not like 'RMAN%';

 SID OPNAME                              SOFAR  TOTALWORK TIME_REMAINING ELAPSED_SECONDS
---------- ------------------------------ ---------- ---------- -------------- ---------------
 2222 Table Scan                          51736      51736              0              12
 2222 Sort Output                         21422      21422              0               7

</pre></p>
<p>Now online index rebuild session is waiting for session 3 (SID 2177), which I started which table scan operation was inprogress</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 2177 AE                         Share                                    None                                     Not Blocking         MYTAB
 2177 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2177 Transaction                Exclusive                                None                                     Blocking             MYTAB
 2222 AE                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                None                                     Share                                    Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 AE                         Share                                    None                                     Not Blocking         MYTAB
 2222 OD                         Exclusive                                None                                     Not Blocking         MYTAB
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         MYTAB
 2222 DL                         Row-X (SX)                               None                                     Not Blocking         MYTAB
 2222 OD                         Share                                    None                                     Not Blocking         MYTAB
 2222 Transaction                None                                     Share                                    Not Blocking         MYTAB
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         MYTAB
 2222 DML                        Share                                    None                                     Not Blocking         MYTAB
 2222 Transaction                Exclusive                                None                                     Not Blocking         MYTAB

</pre></p>
<p>Unless I commit that session index rebuild will wait. If I start another session now (session 4) and commit session 3, index rebuild will still wait for session 4 to complete.<br />
Like this it can continue to wait until all transactions are done.</p>
<p>Example I started session 4 (SID 2223 ) and ran DML, commited in session 3</p>
<p>now index rebuild session (SID 2222) is waiting for session 4.</p>
<p><pre class="brush: sql;">

ORACLE_ID LOCK_TYPE                  LOCK_HELD                                LOCK_REQUESTED                           STATUS               OBJECT_NAME
---------- -------------------------- ---------------------------------------- ---------------------------------------- -------------------- ------------------------------
 2223 AE                         Share                                    None                                     Not Blocking         MYTAB
 2223 DML                        Row-X (SX)                               None                                     Not Blocking         MYTAB
 2223 Transaction                Exclusive                                None                                     Blocking             MYTAB
 2222 Transaction                None                                     Share                                    Not Blocking         SYS_JOURNAL_98701
 2222 AE                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 OD                         Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         SYS_JOURNAL_98701
 2222 DML                        Share                                    None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                Exclusive                                None                                     Not Blocking         SYS_JOURNAL_98701
 2222 Transaction                None                                     Share                                    Not Blocking         MYTAB
 2222 AE                         Share                                    None                                     Not Blocking         MYTAB
 2222 OD                         Exclusive                                None                                     Not Blocking         MYTAB
 2222 OD                         Share                                    None                                     Not Blocking         MYTAB
 2222 DML                        Row-S (SS)                               None                                     Not Blocking         MYTAB
 2222 DML                        Share                                    None                                     Not Blocking         MYTAB
 2222 Transaction                Exclusive                                None                                     Not Blocking         MYTAB

</pre></p>
<p>So main difference in case of online index rebuild procedure is online index rebuild process gives precedence to other DML sessions to acquire locks. The process has become less intrusive now.</p>
<p>Hope this helps !!</p>
<br />Filed under: <a href='http://avdeo.com/category/oracle-database-10g/'>Oracle Database 10g</a>, <a href='http://avdeo.com/category/oracle-database-11g/'>Oracle Database 11g</a> Tagged: <a href='http://avdeo.com/tag/11g-index-rebuild/'>11g index rebuild</a>, <a href='http://avdeo.com/tag/journal-table/'>journal table</a>, <a href='http://avdeo.com/tag/online-index-rebuild/'>online index rebuild</a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/advait.wordpress.com/832/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/advait.wordpress.com/832/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/advait.wordpress.com/832/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/advait.wordpress.com/832/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/advait.wordpress.com/832/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/advait.wordpress.com/832/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/advait.wordpress.com/832/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/advait.wordpress.com/832/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=avdeo.com&amp;blog=1226407&amp;post=832&amp;subd=advait&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://avdeo.com/2011/03/17/oracle-index-rebuild-online-10g-vs-11g/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e634d55129526d1676fc4fcf1da0a653?s=96&#38;d=identicon&#38;r=G" medium="image">
			<media:title type="html">advait</media:title>
		</media:content>
	</item>
	</channel>
</rss>
