<?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"
	>

<channel>
	<title>Blogging about Software Development &#187; Databases</title>
	<atom:link href="http://www.bloggingaboutjava.org/category/oracle/databases/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.bloggingaboutjava.org</link>
	<description>Blogging about Software Development</description>
	<pubDate>Wed, 03 Dec 2008 15:09:11 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.2</generator>
	<language>en</language>
			<item>
		<title>Guru4Pro: Tom Kyte @ Logica</title>
		<link>http://www.bloggingaboutjava.org/2008/10/tom-kyte-logica/</link>
		<comments>http://www.bloggingaboutjava.org/2008/10/tom-kyte-logica/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 12:17:51 +0000</pubDate>
		<dc:creator>Roel</dc:creator>
		
		<category><![CDATA[Announcements]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Events]]></category>

		<category><![CDATA[Guru4Pro]]></category>

		<category><![CDATA[Oracle]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutjava.org/?p=375</guid>
		<description><![CDATA[In the afternoon of November 3 Oracle guru Tom Kyte will talk about &#8220;11 Things about 11g&#8221; at the Logica office in Amstelveen (near Amsterdam). I have attended this presentation at ODTUG this year and I assure you it&#8217;s worthwhile! After his presentation Tom will also do an AskTom Live session. So a great opportunity [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://2.bp.blogspot.com/_1PcG7Kr-Zg8/SO85sMYEVgI/AAAAAAAAAEw/WqxtuY4YHMw/s200/asktom4.gif" alt="" align="left" />In the afternoon of November 3 Oracle guru Tom Kyte will talk about &#8220;<em>11 Things about 11g</em>&#8221; at the Logica office in Amstelveen (near Amsterdam). I have attended this presentation at ODTUG this year and I assure you it&#8217;s worthwhile! After his presentation Tom will also do an <a href="http://asktom.oracle.com/pls/asktom/f?p=100:1">AskTom</a> Live session. So a great opportunity to enhance your knowledge with everything you wanted to know about Oracle but you never dared to ask&#8230;<br />
There is more info on the <a href="http://www.logica.nl/guru4pro+-+tom+kyte/400013739">Logica site</a> (in Dutch, but Tom will do his presentation in English ofcourse). You can also register (&#8221;aanmeldingsformulier&#8221;) there.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2008/10/tom-kyte-logica/feed/</wfw:commentRss>
		</item>
		<item>
		<title>APEX application for maintaining personal contracts</title>
		<link>http://www.bloggingaboutjava.org/2008/09/apex-application-for-maintaining-personal-contracts/</link>
		<comments>http://www.bloggingaboutjava.org/2008/09/apex-application-for-maintaining-personal-contracts/#comments</comments>
		<pubDate>Fri, 19 Sep 2008 12:35:34 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
		
		<category><![CDATA[Apex]]></category>

		<category><![CDATA[Databases]]></category>

		<category><![CDATA[General]]></category>

		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutjava.org/?p=369</guid>
		<description><![CDATA[APEX is famous for it&#8217;s useful applications, so when the idea poped into my head that I would like to track my personal contracts, APEX was first in line to develop such an application.
The purpose of this app is to be able to track longrunning contracts with their renewalperiods. One month before you should end [...]]]></description>
			<content:encoded><![CDATA[<p>APEX is famous for it&#8217;s useful applications, so when the idea poped into my head that I would like to track my personal contracts, APEX was first in line to develop such an application.</p>
<p>The purpose of this app is to be able to track longrunning contracts with their renewalperiods. One month before you should end the contract (checked on contract enddate) you&#8217;ll receive an email. I used Oracle&#8217;s DBMS_SCHEDUAL to call the procedure that sends out the email. Also, it has an authentication scheme so that different users can use this online app. Although it&#8217;s dutch, everyone can apply <a title="Contract Notifier" href="http://apex.oracle.com/pls/otn/f?p=23729" target="_blank">now</a>.</p>
<p> <a href="http://apex.oracle.com/pls/otn/f?p=23729">http://apex.oracle.com/pls/otn/f?p=23729</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2008/09/apex-application-for-maintaining-personal-contracts/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The use of dynamic vs aggregated functions</title>
		<link>http://www.bloggingaboutjava.org/2007/10/the-use-of-dynamich-vs-aggregated-functions/</link>
		<comments>http://www.bloggingaboutjava.org/2007/10/the-use-of-dynamich-vs-aggregated-functions/#comments</comments>
		<pubDate>Wed, 03 Oct 2007 11:00:41 +0000</pubDate>
		<dc:creator>Jasper</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[PL/SQL]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/?p=265</guid>
		<description><![CDATA[An eyeopener for me when constructing sql queries in a complex environment was the use of analytic functions. As appose to aggregated functions, you can use more analytic functions on one table instead of constructing multiple inline views to accomplish &#8220;the same&#8221;.
For those of you who like to see examples:
select job_id
, sum(salary)
from employees
group by job_id;
has [...]]]></description>
			<content:encoded><![CDATA[<p>An eyeopener for me when constructing sql queries in a complex environment was the use of analytic functions. As appose to aggregated functions, you can use more analytic functions on one table instead of constructing multiple inline views to accomplish &#8220;the same&#8221;.</p>
<p>For those of you who like to see examples:</p>
<p><code>select job_id<br />
, sum(salary)<br />
from employees<br />
group by job_id;</code></p>
<p>has the same result as:</p>
<p><code>select distinct job_id<br />
, sum(salary) over (partition by job_id)<br />
from employees;<br />
</code></p>
<p>But using the second query you could also add for example, the avarage salary per job:</p>
<p><code>select distinct job_id<br />
, sum(salary) over (partition by job_id)<br />
, avg(salary) over (partition by job_id)<br />
from employees;</code></p>
<p>If I would want this result using an aggregated function, I would have to use a inline views, like this:</p>
<p><code>select s.job_id, s.ssal, a.asal<br />
from ( select job_id, sum(salary) ssal<br />
	   from employees<br />
	   group by job_id<br />
	 ) s<br />
,	 ( select job_id, avg(salary) asal<br />
	   from employees<br />
	   group by job_id<br />
	 ) a<br />
where s.job_id = a.job_id<br />
order by s.job_id<br />
;</code></p>
<p>So that makes the code much more readable. Advantage number one&#8230;</p>
<p>But also, something that can&#8217;t be accomplished using aggregated functions, is selecting other data besides the grouped data from the table. Such as:</p>
<p><code>select job_id<br />
,	   first_name<br />
, 	   sum(salary) over (partition by job_id) ssal<br />
,	   avg(salary) over (partition by job_id) asal<br />
from employees<br />
order by job_id<br />
;</code></p>
<p>Now I can make much better use of this data, and it&#8217;s less code!</p>
<p>Sort of automatically I figured that using analytic functions would also be quicker. Because after all, we would only have to do a full table scan once. But I found myself to be greatly mistaken when I checked the explain plans of two different statements, one using aggregated and one using analytic functions. Explain plan for the query above using aggregated function vs the analytic functions shows that the aggregated function has much better performance.</p>
<p>So by using analytic functions on large sets of data&#8230; causes some performance difficulties. So using aggregated functions would be better here?</p>
<p>I started searching the net for explanations. Discovering first of all, that analytic functions should not be used to aggregate. Because when you aggregate you return only the aggregated rows. By using a distinct in the query&#8217;s above using the analytic functions, you get the same result, but for every row that is selected, the analytic function is added. So logically this is costing us performance.</p>
<p>I discovered this by reading an article on asktom.com. So I guess I should always ask myself the question: do I want to analyse or aggregate?&#8230;</p>
<p>Other articles show that the use of analytic of aggregated functions is all up to you. What&#8217;s your gain? What&#8217;s your personal preference?</p>
<p>I think analytic functions are fantastic and I couldn&#8217;t stop using them even if I wanted to <img src='http://www.bloggingaboutjava.org/cms/wordpress2/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> But I guess it&#8217;s up to you to deside&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/10/the-use-of-dynamich-vs-aggregated-functions/feed/</wfw:commentRss>
		</item>
		<item>
		<title>I Struck Oil at Miracle Oracle Open World 2007</title>
		<link>http://www.bloggingaboutjava.org/2007/10/i-struck-oil-at-miracle-oracle-open-world-2007/</link>
		<comments>http://www.bloggingaboutjava.org/2007/10/i-struck-oil-at-miracle-oracle-open-world-2007/#comments</comments>
		<pubDate>Tue, 02 Oct 2007 13:09:02 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Oracle Infrastructure]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/i-struck-oil-at-miracle-oracle-open-world-2007</guid>
		<description><![CDATA[This was my second time at the Miracle Conference at Lalandia in Denmark.
Again it was &#8220;power-pact&#8221;.
Mogens Norgaard explained that a lot of conferences have about 80% information and only 20% networking possibilities. This conference is different. Mogens managed to increase the 20% networking up to 80% while still remaining 80% of usefull information. The way [...]]]></description>
			<content:encoded><![CDATA[<p>This was my second time at the Miracle Conference at Lalandia in Denmark.<br />
Again it was &#8220;power-pact&#8221;.</p>
<p>Mogens Norgaard explained that a lot of conferences have about 80% information and only 20% networking possibilities. This conference is different. Mogens managed to increase the 20% networking up to 80% while still remaining 80% of usefull information. The way he does this is by supplying Miracle ÃƒËœl. As a former geophycicist I now know how it is to struck Miracle ÃƒËœl in the search of indepth Oracle knowledge.</p>
<p>Next to networking with 170 Oracle Database Professionals you could pick out 7 presentations from three tracks all given by experts in the Oracle database field. My picks where Tapio Lahdenmaki, Michael MÃƒÂ¶ller, Cary Millsap (twice), Graham Wood (twice) and Jonathan Lewis.</p>
<p>Tapio&#8217;s : rethink your indexes, really gave some hands-on advice. Basically inadequate indexing comes from three things:<br />
-	Important Index Missing<br />
-	Important Columns Missing<br />
-	Wrong Column Order<br />
You even learn new jargon : like Fat and Semi-Fat indexes.<br />
Jonathan Lewis remarked that : &#8220;Sometimes the optimizer has to be persuaded that Tapio&#8217;s index design is right.&#8221;</p>
<p>Then there is the story of Micheal MÃƒÂ¶ller. On the opening evening of this event, Michael gave us a very well executed presentation of Murphy&#8217;s Law in practice. Although he had a quadrible back-up the presentation ended with all the lights out in the conference room. It was hilarious. I think Michael has followed a workshop at John Cleese&#8217;s. The day after he warned that his presentation on Standby database really contained a serious demo. As always something went wrong now it was a nasty Windows message saying  going in Standby mode<br />
The demo had to be postponed to the afternoon.</p>
<p>Cary Millsap showed that almost every body is a performance guy like him.<br />
If you say faster = better, then you are a performance guy as well.<br />
Performance analysis is the study of &#8220;how long something takes&#8221;. Essential is the concept of a profile: it is full accounting of the time you care about. His story about Bob, Bob&#8217;s boy, and the bicycle that became a Ferrari is classic. And it shows how you can explain performance management to people in the business.</p>
<p>Cary also made clear that diagnose-ability is a feature that every application should have. This cost resources just like any other application feature. Jonathan Lewis gave it two different names depending on the situation: &#8220;Overhead&#8221; or &#8220;Infrastructure&#8221;. We need pre-emptive logging in our code.</p>
<p>In Cary&#8217;s second session he explained why you can&#8217;t see your real performance problems. Undiagnosed skew is the common cause why performance projects fail. In many cases it does more harm to go even look at totals aggregated across tasks. He introduced a new Law called Bragan&#8217;s Law which says that: If the number you look at it is a total or average, then there is a list underneath. Look at the list is there skew? A nice example of Bragan&#8217;s law was given: Statistici will say that your comfortable if you stand in two buckets of water: One Very Hot and one Ice Cold Ã¯ÂÅ . Skew can be detected in raw 10046 trace files.</p>
<p>The session&#8217;s of Graham Wood where also interesting. I always like to here Oracle&#8217;s side of the story (And not from a Marketing Guy). Did you for instance knew that TK was a performance group in Oracle and PROF there profiler? Graham is the founding father of Statspack, the last years at Oracle he was the architect of DB Time, AWR, ADDM and ASH. Did you knew that dbms_monitor could trace a Module persistent? Every time it starts it is traced.<br />
Did you know that TKPROF cursors must be closed to get plan data? This sometimes is troublesome due to the fact that Oracle has some features to keep cursors open for a while.<br />
Graham showed me that ASH is a great feature in Oracle, it is always on. It samples every second all active session activity data (On CPU, Or Waiting on non-idle events). The design goal from Oracle was to hold one hour of activity in memory. You don&#8217;t loose data because every hour the ASH data is flushed to disk or when it is 66% full. With a MOD(10) only 1 of 10 samples is kept in dba_hist_active_sess_history. Although this data does not capture every read and wait it is statistically valid, and you can do all kinds of statistical analysis on it in several dimensions (Like Application, Program, Module, Action, Client-Id and Service.</p>
<p>During the gala dinner I had the chance to sit opposite of Graham Wood, and go into more detail on several of his favorite topics.</p>
<p>The second presentation of Graham focused on DB Time. It combines the best of the YAPP and Method-R methods. It has low intrusion and still has detailed data. You don&#8217;t need to scope your collections, you have no requirements to reproduce the problem (This is THE major, difference with Method R!), and you can investigate concurrency problems like locking. ASH tracks down the blocking SID and has details from this SID logged as well.</p>
<p>In short: DB Time is database load, DB time increases when more work is done in the database.<br />
The fundamental performance metric is Average Active Sessions (AAS) = DB Time / Wall Clock Time. The recommendations in ADDM are all focused in reducing DB Time.</p>
<p>Last but not least: Jonathan Lewis gave some very nice tips in the understanding of Statspack data. Jonathan showed that you have to practice a lot with Statspack data. The easiest way is to practice generating the symptoms yourself. Just test and run a full table scan a 100 times and look how it is reported in Statspack. Often you expect to see high &#8220;db file&#8221; wait events but it turns out to be CPU-intensive (Short explanation is that you might have read from the SAN-cache). Jonathan also mentioned that Skewed data in Wait events is visible in the 10gR2 Statspack report. His final statement: &#8220;Knowing the answers, before people ask questions, make you look clever&#8221; was a remarkable statement.</p>
<p>To wrap it up. I really liked this conference. The presentations/presenters were inspiring.<br />
The food and beverages where fine. And no people got hurt in the swimming-pool (remember last years pictures). Can&#8217;t wait for MOOW08.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/10/i-struck-oil-at-miracle-oracle-open-world-2007/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Blogging about 11g - Part 10 - Enhanced Optimizer Statistics Maintenance</title>
		<link>http://www.bloggingaboutjava.org/2007/09/blogging-about-11g-part-10-enhanced-optimizer-statistics-maintenance/</link>
		<comments>http://www.bloggingaboutjava.org/2007/09/blogging-about-11g-part-10-enhanced-optimizer-statistics-maintenance/#comments</comments>
		<pubDate>Tue, 25 Sep 2007 09:34:46 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Oracle Infrastructure]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/blogging-about-11g-part-10-enhanced-optimizer-statistics-maintenance</guid>
		<description><![CDATA[In Oracle 11g you now can modify gather_database_stats default values with  set_global_prefs, set_database_prefs, set_schema_prefs, set_table_prefs in the dbms_stats package.
An even greater new feature is that in Oracle Database 11g, you can separate statistic gathering from statistic publishing.
This allows you to control when new statistics are published. Everybody must have run in to this once, [...]]]></description>
			<content:encoded><![CDATA[<p>In Oracle 11g you now can modify gather_database_stats default values with  set_global_prefs, set_database_prefs, set_schema_prefs, set_table_prefs in the dbms_stats package.</p>
<p>An even greater new feature is that in Oracle Database 11g, you can separate statistic gathering from statistic publishing.</p>
<p>This allows you to control when new statistics are published. Everybody must have run in to this once, that queries ran differently because part of the statistics where just refreshed or being gathered.</p>
<p><strong>TEST STEPS modifying preferences</strong></p>
<p>About this subject Oracle wrote some Oracle By Example (OBE) scripts available at:</p>
<p><a> http://otnbeta.us.oracle.com/db11gr1/trng/obes/index.htm</a></p>
<p>This really speeded up the testing of this new feature.<br />
Get the custemers_obe.dmp file and import it under the SH Schema.</p>
<p>imp sh/sh file= customers_obe.dmp log=imp.log full=y</p>
<p>Import: Release 11.1.0.3.0 - Beta on Thu Mar 29 13:04:10 2007</p>
<p>Copyright (c) 1982, 2006, Oracle.  All rights reserved.</p>
<p>Connected to: Oracle Database 11g Enterprise Edition Release 11.1.0.3.0 - Beta<br />
With the Partitioning, OLAP and Data Mining options</p>
<p>Export file created by EXPORT:V11.01.00 via conventional path<br />
import done in US7ASCII character set and AL16UTF16 NCHAR character set<br />
import server uses WE8MSWIN1252 character set (possible charset conversion)<br />
. importing SH&#8217;s objects into SH<br />
. importing SH&#8217;s objects into SH<br />
. . importing table                &#8220;CUSTOMERS_OBE&#8221;        630 rows imported<br />
Import terminated successfully without warnings.</p>
<p>SQL> connect sh/sh</p>
<p>CHECK Default Settings of STALE_PERCENT. Note that STALE_PERCENT determines the percentage of rows<br />
in a table that have to change before the statistics on that table are deemed stale and should be regathered</p>
<p>select dbms_stats.get_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;SH&#8217;, &#8216;SALES&#8217;) stale_percent<br />
from dual;</p>
<p>STALE_PERCENT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
10</p>
<p>To change the default setting for the database do:<br />
execute dbms_stats.set_global_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;13&#8242;);</p>
<p>PL/SQL procedure successfully completed.</p>
<p>And Check:<br />
SQL> connect sh/sh<br />
select dbms_stats.get_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;SH&#8217;, &#8216;SALES&#8217;) stale_percent<br />
from dual;</p>
<p>STALE_PERCENT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
13</p>
<p>11g allows to change this parameter even on a table by table basis.</p>
<p>For example set the STALE_PERCENT for the SALES table to 65%.<br />
execute dbms_stats.set_table_prefs(&#8217;SH&#8217;, &#8216;SALES&#8217;, &#8216;STALE_PERCENT&#8217;, &#8216;65&#8242;);</p>
<p>PL/SQL procedure successfully completed.</p>
<p>select dbms_stats.get_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;SH&#8217;, &#8216;SALES&#8217;) stale_percent<br />
from dual;</p>
<p>STALE_PERCENT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
65</p>
<p>Note that another table the product table still uses 13%.</p>
<p>SQL> select dbms_stats.get_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;SH&#8217;, &#8216;PRODUCTS&#8217;) stale_percent<br />
from dual;</p>
<p>STALE_PERCENT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
13</p>
<p>If you want to reset everything back to the default. You first need to delete the table preference you set on SALES so that the table has the global default value. Execute the following SQL script:</p>
<p>execute dbms_stats.delete_table_prefs(&#8217;SH&#8217;, &#8216;SALES&#8217;, &#8216;STALE_PERCENT&#8217;);</p>
<p>select dbms_stats.get_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;SH&#8217;, &#8216;SALES&#8217;) stale_percent<br />
from dual;</p>
<p>STALE_PERCENT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
13</p>
<p>Now you have to reconnect as system or sysdba to reset the global defaults. You don&#8217;t need to remember what the default values are, you simple need to set the preference value to null and that restores the &#8220;factory&#8221; default value.</p>
<p>Execute the following SQL script:</p>
<p>SQL> execute dbms_stats.set_global_prefs(&#8217;STALE_PERCENT&#8217;, null);</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> conn sh/sh<br />
Connected.<br />
SQL> select dbms_stats.get_prefs(&#8217;STALE_PERCENT&#8217;, &#8216;SH&#8217;, &#8216;SALES&#8217;) stale_percent<br />
from dual;</p>
<p>STALE_PERCENT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
10</p>
<p>###</p>
<p>TEST STEPS Gathering Private Statistics</p>
<p>You first want to alter the date format and reset the stats for the CUSTOMERS_OBE table.</p>
<p>Execute the following commands:<br />
connect sh/sh<br />
alter session set nls_date_format=&#8217;mm/dd hh24:mi:ss&#8217;;</p>
<p>&#8211; delete statistics<br />
exec dbms_stats.delete_table_stats(&#8217;SH&#8217;, &#8216;CUSTOMERS_OBE&#8217;);</p>
<p>Now you can review the public statistics for the CUSTOMERS_OBE table.<br />
With the following command:</p>
<p>select table_name, last_analyzed analyze_time, num_rows, blocks, avg_row_len<br />
from user_tables<br />
where table_name = &#8216;CUSTOMER_OBE&#8217;;</p>
<p>no rows selected</p>
<p>&#8211; indexes<br />
select index_name, last_analyzed ANALYZE_TIME, num_rows,<br />
       leaf_blocks, distinct_keys<br />
from user_indexes<br />
where table_name = &#8216;CUSTOMER_OBE&#8217;<br />
order by index_name;</p>
<p>no rows selected</p>
<p>&#8211; columns<br />
select column_name, last_analyzed ANALYZE_TIME, num_distinct,<br />
       num_nulls, density<br />
from user_tab_columns<br />
where table_name = &#8216;CUSTOMER_OBE&#8217;<br />
order by column_name;</p>
<p>COLUMN_NAME                    ANALYZE_TIME   NUM_DISTINCT  NUM_NULLS    DENSITY<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
COUNTRY_ID<br />
CUST_CITY<br />
CUST_CREDIT_LIMIT<br />
CUST_EMAIL<br />
CUST_FIRST_NAME<br />
CUST_GENDER<br />
CUST_ID<br />
CUST_INCOME_LEVEL<br />
CUST_LAST_NAME<br />
CUST_MAIN_PHONE_NUMBER<br />
CUST_MARITAL_STATUS<br />
CUST_POSTAL_CODE<br />
CUST_STATE_PROVINCE<br />
CUST_STREET_ADDRESS<br />
CUST_YEAR_OF_BIRTH</p>
<p>15 rows selected.</p>
<p>Now review the private statistics for the CUSTOMERS_OBE table.</p>
<p>select table_name, last_analyzed &#8220;analyze time&#8221;, num_rows, blocks, avg_row_len<br />
from user_tab_private_stats<br />
where table_name = &#8216;CUSTOMER_OBE&#8217; and partition_name is null;</p>
<p>&#8211; indexes<br />
select index_name, last_analyzed &#8220;analyze time&#8221;, num_rows,<br />
       leaf_blocks, distinct_keys<br />
from user_ind_private_stats<br />
where table_name = &#8216;CUSTOMER_OBE&#8217; and partition_name is null<br />
order by index_name;</p>
<p>select column_name, last_analyzed &#8220;analyze time&#8221;, num_distinct,<br />
       num_nulls, density<br />
from user_col_private_stats<br />
where table_name = &#8216;CUSTOMER_OBE&#8217; and partition_name is null<br />
order by column_name;</p>
<p>Now 3 times no rows selected.</p>
<p>Currently the CUSTOMERS_OBE table does not have any public or private statistics.</p>
<p><strong>NOTE THAT the default behavior in Oracle Database 11g is the same as before where the statistic is published<br />
as soon as the gather is complete. </strong></p>
<p>You can check the preferences by executing the following script:</p>
<p>select dbms_stats.get_prefs(&#8217;PUBLISH&#8217;) publish from dual;</p>
<p>PUBLISH<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
TRUE</p>
<p>You can also check or change the publish mode at a table level. You want to check the publish preference<br />
value for the CUSTOMERS_OBE table. It should be the same as the global default.</p>
<p>Check this with:</p>
<p>select dbms_stats.get_prefs(&#8217;PUBLISH&#8217;, &#8216;SH&#8217;, &#8216;CUSTOMERS_OBE&#8217;) publish from dual;</p>
<p>PUBLISH<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
TRUE</p>
<p>Set the CUSTOMERS_OBE tables publish value to false. This means that any statistics gathered from now on<br />
will not be automatically published. Execute the following SQL script:</p>
<p>exec dbms_stats.set_table_prefs(&#8217;SH&#8217;, &#8216;CUSTOMERS_OBE&#8217;, &#8216;PUBLISH&#8217;, &#8216;false&#8217;);</p>
<p>PL/SQL procedure successfully completed.</p>
<p>select dbms_stats.get_prefs(&#8217;PUBLISH&#8217;, &#8216;SH&#8217;, &#8216;CUSTOMERS_OBE&#8217;) publish from dual;</p>
<p>PUBLISH<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
FALSE</p>
<p>Now you can gather statistics on the CUSTOMERS_OBE table by executing the following:</p>
<p>execute dbms_stats.gather_table_stats(&#8217;SH&#8217;, &#8216;CUSTOMERS_OBE&#8217;);</p>
<p>PL/SQL procedure successfully completed.</p>
<p>Since the CUSTOMERS_OBE table has its publish preference set to false there should not be any<br />
public statistics for this table after the gather statistics.</p>
<p>Check with:</p>
<p>&#8211; tables<br />
select table_name, last_analyzed analyze_time, num_rows, blocks, avg_row_len<br />
from user_tables<br />
where table_name = &#8216;CUSTOMER_OBE&#8217;;</p>
<p>TABLE_NAME                     ANALYZE_TIME     NUM_ROWS     BLOCKS AVG_ROW_LEN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8211;<br />
CUSTOMERS_OBE</p>
<p>&#8211; indexes<br />
select index_name, last_analyzed ANALYZE_TIME, num_rows,<br />
       leaf_blocks, distinct_keys<br />
from user_indexes<br />
where table_name = &#8216;CUSTOMER_OBE&#8217;<br />
order by index_name;</p>
<p>INDEX_NAME               ANALYZE_TIME     NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;-<br />
OBE_CUST_CRED_LMT_IND</p>
<p>&#8211; columns<br />
select column_name, last_analyzed ANALYZE_TIME, num_distinct,<br />
       num_nulls, density<br />
from user_tab_columns<br />
where table_name = &#8216;CUSTOMER_OBE&#8217;<br />
order by column_name;</p>
<p>COLUMN_NAME                    ANALYZE_TIME   NUM_DISTINCT  NUM_NULLS    DENSITY<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
COUNTRY_ID<br />
CUST_CITY<br />
CUST_CREDIT_LIMIT<br />
CUST_EMAIL<br />
CUST_FIRST_NAME<br />
CUST_GENDER<br />
CUST_ID<br />
CUST_INCOME_LEVEL<br />
CUST_LAST_NAME<br />
CUST_MAIN_PHONE_NUMBER<br />
CUST_MARITAL_STATUS<br />
CUST_POSTAL_CODE<br />
CUST_STATE_PROVINCE<br />
CUST_STREET_ADDRESS<br />
CUST_YEAR_OF_BIRTH</p>
<p>15 rows selected.</p>
<p>But now check to see if you have private statistics.</p>
<p>&#8211; tables<br />
select table_name, last_analyzed &#8220;analyze time&#8221;, num_rows, blocks, avg_row_len<br />
from user_tab_private_stats<br />
where table_name = &#8216;CUSTOMER_OBE&#8217; and partition_name is null;</p>
<p>TABLE_NAME                     analyze time     NUM_ROWS     BLOCKS AVG_ROW_LEN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8211;<br />
CUSTOMERS_OBE                  03/29 13:33:01        630         12  137.646032</p>
<p>&#8211; indexes<br />
select index_name, last_analyzed &#8220;analyze time&#8221;, num_rows,<br />
       leaf_blocks, distinct_keys<br />
from user_ind_private_stats<br />
where table_name = &#8216;CUSTOMER_OBE&#8217; and partition_name is null<br />
order by index_name;</p>
<p>INDEX_NAME               analyze time     NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;-<br />
OBE_CUST_CRED_LMT_IND    03/29 13:33:02        630           2             8</p>
<p>&#8211; columns<br />
select column_name, last_analyzed &#8220;analyze time&#8221;, num_distinct,<br />
       num_nulls, density<br />
from user_col_private_stats<br />
where table_name = &#8216;CUSTOMER_OBE&#8217; and partition_name is null<br />
order by column_name;</p>
<p>COLUMN_NAME                    analyze time   NUM_DISTINCT  NUM_NULLS    DENSITY<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
COUNTRY_ID                     03/29 13:32:59           19          0 .052631579<br />
CUST_CITY                      03/29 13:32:59          300          0 .003333333<br />
CUST_CREDIT_LIMIT              03/29 13:32:59            8          0       .125<br />
CUST_EMAIL                     03/29 13:32:59          400          0      .0025<br />
CUST_FIRST_NAME                03/29 13:32:59          450          0 .002222222<br />
CUST_GENDER                    03/29 13:32:59            2          0         .5<br />
CUST_ID                        03/29 13:32:59          630          0 .001587302<br />
CUST_INCOME_LEVEL              03/29 13:32:59           12          0 .083333333<br />
CUST_LAST_NAME                 03/29 13:32:59          400          0      .0025<br />
CUST_MAIN_PHONE_NUMBER         03/29 13:32:59          630          0 .001587302<br />
CUST_MARITAL_STATUS            03/29 13:32:59            2        234         .5<br />
CUST_POSTAL_CODE               03/29 13:32:59          301          0 .003322259<br />
CUST_STATE_PROVINCE            03/29 13:32:59          120          0 .008333333<br />
CUST_STREET_ADDRESS            03/29 13:32:59          630          0 .001587302<br />
CUST_YEAR_OF_BIRTH             03/29 13:32:59           66          0 .015151515</p>
<p>15 rows selected.</p>
<p>All of the statistics on the CUSTOMERS_OBE table are private. If you wanted to test the new statistics<br />
you could export them from the private statistics table and import them into a test system.<br />
If they were found to be unacceptable you could simply delete them from the private statistics tables<br />
without effecting production.</p>
<p>To test a query without using the private statistics do:<br />
alter session set optimizer_private_statistics = false;<br />
alter session set optimizer_dynamic_sampling = 0;</p>
<p>Now you can get and display an explain plan for your query.</p>
<p>explain plan for<br />
select * from customers_obe where CUST_CREDIT_LIMIT=1500;</p>
<p>Explained.</p>
<p>set linesize 140<br />
select plan_table_output plan from table(dbms_xplan.display(&#8217;plan_table&#8217;,null,&#8217;serial&#8217;))<br />
/</p>
<p>PLAN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan hash value: 278193547</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
| Id  | Operation                   | Name          | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
|   0 | SELECT STATEMENT            |               |     1 |   208 |     1   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS BY INDEX ROWID| CUSTOMERS_OBE |     1 |   208 |     1   (0)| 00:00:01 |<br />
|*  2 |   INDEX RANGE SCAN          | CUSTOMERS_OBE |     1 |       |     1   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>PLAN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>   2 - access(&#8221;CUST_CREDIT_LIMIT&#8221;=1500)</p>
<p>This is not a very optimal plan since it requeries an index look-up and then a single row access of the table<br />
for every row that has a CUST_CREDIT_LIMIT=1500. Over 20% of the rows in the table have the CUST_CREDIT_LIMIT value of 1500.<br />
As the OBE_CUSTOMERS table grows this plan will get slower and slower as the number of rows matching the query increases.</p>
<p>To see if the optimizer does better when it uses the statistics in the private statistic tables, you need to set<br />
optimizer_private_statistics to true by running the following script:</p>
<p>alter session set optimizer_private_statistics = true;</p>
<p>Session altered.</p>
<p>explain plan for<br />
select * from customers_obe where CUST_CREDIT_LIMIT=1500;</p>
<p>select plan_table_output plan from table(dbms_xplan.display(&#8217;plan_table&#8217;,null,&#8217;serial&#8217;));</p>
<p>Explained.</p>
<p>PLAN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan hash value: 520139036</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name          | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |               |    79 | 10586 |     4   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| CUSTOMERS_OBE |    79 | 10586 |     4   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>PLAN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>   1 - filter(&#8221;CUST_CREDIT_LIMIT&#8221;=1500)</p>
<p>13 rows selected.</p>
<p>The OBE Guide states that this plan with the private statistics is much better.<br />
You now do a full table scan which retrieves all of the matching rows with a single pass of the table.<br />
This is the plan you want to run in production. We can make them public by executing the following script:</p>
<p>exec dbms_stats.publish_private_stats(null, null);</p>
<p>PL/SQL procedure successfully completed.</p>
<p>Now if you check the public statistics for the CUSTOMERS_OBE table you should see all of the statistics you gathered earlier.</p>
<p>&#8211; tables<br />
select table_name, last_analyzed analyze_time, num_rows, blocks, avg_row_len<br />
from user_tables<br />
where table_name = &#8216;CUSTOMERS_OBE&#8217;;</p>
<p>TABLE_NAME                     ANALYZE_TIME     NUM_ROWS     BLOCKS AVG_ROW_LEN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8211;<br />
CUSTOMERS_OBE                  03/29 13:33:01        630         12         137</p>
<p>&#8211; indexes<br />
select index_name, last_analyzed ANALYZE_TIME, num_rows,<br />
       leaf_blocks, distinct_keys<br />
from user_indexes<br />
where table_name = &#8216;CUSTOMERS_OBE&#8217;<br />
order by index_name;</p>
<p>INDEX_NAME                     ANALYZE_TIME     NUM_ROWS LEAF_BLOCKS DISTINCT_KEYS<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;-<br />
OBE_CUST_CRED_LMT_IND          03/29 13:33:02        630           2             8</p>
<p>&#8211; columns<br />
select column_name, last_analyzed ANALYZE_TIME, num_distinct,<br />
       num_nulls, density<br />
from user_tab_columns<br />
where table_name = &#8216;CUSTOMERS_OBE&#8217;<br />
order by column_name;</p>
<p>COLUMN_NAME                    ANALYZE_TIME   NUM_DISTINCT  NUM_NULLS    DENSITY<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;-<br />
COUNTRY_ID                     03/29 13:32:59           19          0 .052631579<br />
CUST_CITY                      03/29 13:32:59          300          0 .003333333<br />
CUST_CREDIT_LIMIT              03/29 13:32:59            8          0       .125<br />
CUST_EMAIL                     03/29 13:32:59          400          0      .0025<br />
CUST_FIRST_NAME                03/29 13:32:59          450          0 .002222222<br />
CUST_GENDER                    03/29 13:32:59            2          0         .5<br />
CUST_ID                        03/29 13:32:59          630          0 .001587302<br />
CUST_INCOME_LEVEL              03/29 13:32:59           12          0 .083333333<br />
CUST_LAST_NAME                 03/29 13:32:59          400          0      .0025<br />
CUST_MAIN_PHONE_NUMBER         03/29 13:32:59          630          0 .001587302<br />
CUST_MARITAL_STATUS            03/29 13:32:59            2        234         .5<br />
CUST_POSTAL_CODE               03/29 13:32:59          301          0 .003322259<br />
CUST_STATE_PROVINCE            03/29 13:32:59          120          0 .008333333<br />
CUST_STREET_ADDRESS            03/29 13:32:59          630          0 .001587302<br />
CUST_YEAR_OF_BIRTH             03/29 13:32:59           66          0 .015151515</p>
<p>15 rows selected.</p>
<p>Then check the private statistics for the CUSTOMERS_OBE table. From your terminal window, execute the following script:<br />
&#8211; tables<br />
select table_name, last_analyzed &#8220;analyze time&#8221;, num_rows, blocks, avg_row_len<br />
from user_tab_private_stats<br />
where table_name = &#8216;CUSTOMERS_OBE&#8217; and partition_name is null;</p>
<p>&#8211; indexes<br />
select index_name, last_analyzed &#8220;analyze time&#8221;, num_rows,<br />
       leaf_blocks, distinct_keys<br />
from user_ind_private_stats<br />
where table_name = &#8216;CUSTOMERS_OBE&#8217; and partition_name is null<br />
order by index_name;</p>
<p>&#8211; columns<br />
select column_name, last_analyzed &#8220;analyze time&#8221;, num_distinct,<br />
       num_nulls, density<br />
from user_col_private_stats<br />
where table_name = &#8216;CUSTOMERS_OBE&#8217; and partition_name is null<br />
order by column_name;</p>
<p>3 times no rows selected</p>
<p><strong>Notice that your private statistics are now gone because they have been published.</strong></p>
<p>#######<br />
Conclusion: In 11g Enhanced Optimizer Statistics Maintenance is possible.<br />
The default behaviour is the same as in 10g, publish automatically.</p>
<p>Beware to document / monitor private statistics areas. They could have a big impact on the explain plan and<br />
on the performance of the queries on those objects.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/09/blogging-about-11g-part-10-enhanced-optimizer-statistics-maintenance/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Blogging about 11g - Part 9 - Password Complexity Checker</title>
		<link>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-9-password-management/</link>
		<comments>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-9-password-management/#comments</comments>
		<pubDate>Fri, 31 Aug 2007 12:10:17 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Oracle Infrastructure]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/blogging-about-11g-part-9-password-management</guid>
		<description><![CDATA[In Oracle 11g you can enable the built-in Password Complexity Checker function.
Background info can be found in the Database Security Guide.
The Oracle Database provides a sample password verification function in the PL/SQL script UTLPWDMG.SQL
(located in ORACLE_BASE/ORACLE_HOME/RDBMS/ADMIN) that, when enabled, checks whether users are correctly creating or modifying their passwords. The UTLPWDMG.SQL script provides two password [...]]]></description>
			<content:encoded><![CDATA[<p>In Oracle 11g you can enable the built-in Password Complexity Checker function.</p>
<p>Background info can be found in the Database Security Guide.</p>
<p>The Oracle Database provides a sample password verification function in the PL/SQL script UTLPWDMG.SQL<br />
(located in ORACLE_BASE/ORACLE_HOME/RDBMS/ADMIN) that, when enabled, checks whether users are correctly creating or modifying their passwords. The UTLPWDMG.SQL script provides two password verification functions: one for previous releases of Oracle Database (which is commented out) and an updated version for Oracle Database Release 11g.</p>
<p>The UTLPWDMG.SQL script checks for the following when users create or modify passwords:<br />
-The password contains no fewer than 8 characters.<br />
-The password is not the same as the user name, nor is it the user name spelled backward or with digits appended.<br />
-The password is not the same as the server name or the server name with the digits 1:100 appended.<br />
-The password is not too simple, for example, welcome1, database1, account1, user1234, password1, oracle, oracle123, computer1, abcdefg1, or change_on_install.<br />
-The password includes at least 1 digit and 1 alphabetic character.<br />
-The password differs from the previous password by at least 3 letters.</p>
<p>Now Lets Test.</p>
<p>SQL> show user<br />
USER is &#8220;SYS&#8221;<br />
SQL> @?\rdbms\admin\utlpwdmg</p>
<p>Function created.</p>
<p>Profile changed.</p>
<p>Function created.</p>
<p>SQL> alter user scott identified by tiger1;<br />
alter user scott identified by tiger1<br />
*<br />
ERROR at line 1:<br />
ORA-28003: password verification for the specified password failed<br />
ORA-20001: Password length less than 8</p>
<p>SQL> alter user scott identified by welcome1;<br />
alter user scott identified by welcome1<br />
*<br />
ERROR at line 1:<br />
ORA-28003: password verification for the specified password failed<br />
ORA-20006: Password too simple</p>
<p>SQL> alter user scott identified by change_on_install;<br />
alter user scott identified by change_on_install<br />
*<br />
ERROR at line 1:<br />
ORA-28003: password verification for the specified password failed<br />
ORA-20006: Password too simple</p>
<p>SQL> alter user scott identified by oracle23;<br />
alter user scott identified by oracle23<br />
*<br />
ERROR at line 1:<br />
ORA-28003: password verification for the specified password failed<br />
ORA-20007: Password too simple</p>
<p>SQL> alter user scott identified by manager1;</p>
<p>User altered.</p>
<p>Well what is simple and what is not. The function works for what its worth &#8230;</p>
<p>#######<br />
Conclusion: In 11g a built-in password complexity function can be used to rapidly enforce a stonger password.</p>
<p>I believe this verification function was already available in 8i or 9i.<br />
So not very new feature, it is however very easy to enable. Run the utlpwdmg.sql as SYS and you are done!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-9-password-management/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Blogging about 11g Part 8 - Interval Partitioning</title>
		<link>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-8-interval-partitioning/</link>
		<comments>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-8-interval-partitioning/#comments</comments>
		<pubDate>Fri, 24 Aug 2007 14:14:42 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Oracle Infrastructure]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/blogging-about-11g-part-8-interval-partitioning</guid>
		<description><![CDATA[DBA&#8217;s can finally use the Automatic Interval Partitioning option.
Test steps following the Oracle By Example (OBE) scripts available at
http://otnbeta.us.oracle.com/db11gr1/trng/obes/index.htm:
&#8211; create interval partitioned table
create table newsales
( prod_id number(6) not null
, cust_id number not null
, time_id date not null
, channel_id char(1) not null
, promo_id number(6) not null
, quantity_sold number(3) not null
, amount_sold number(10,2) not null
)
partition by range [...]]]></description>
			<content:encoded><![CDATA[<p>DBA&#8217;s can finally use the Automatic Interval Partitioning option.</p>
<p>Test steps following the Oracle By Example (OBE) scripts available at<br />
http://otnbeta.us.oracle.com/db11gr1/trng/obes/index.htm:</p>
<p>&#8211; create interval partitioned table</p>
<p>create table newsales<br />
( prod_id number(6) not null<br />
, cust_id number not null<br />
, time_id date not null<br />
, channel_id char(1) not null<br />
, promo_id number(6) not null<br />
, quantity_sold number(3) not null<br />
, amount_sold number(10,2) not null<br />
)<br />
partition by range (time_id)<br />
interval (numtodsinterval(1,&#8217;DAY&#8217;))<br />
( partition p_before_1_jan_2005 values<br />
 less than (to_date(&#8217;01-01-2005&#8242;,&#8217;dd-mm-yyyy&#8217;)))<br />
/</p>
<p>Table  is created.</p>
<p>Show partitions and partition boundaries for the interval partitioned table</p>
<p>select partition_name, high_value<br />
from user_tab_partitions<br />
where table_name = &#8216;NEWSALES&#8217;<br />
order by partition_position<br />
/</p>
<p>PARTITION_NAME            HIGH_VALUE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
P_BEFORE_1_JAN_2005       TO_DATE(&#8217; 2005-01-01 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)</p>
<p>Insert some data after January 1 2005 that forces the creation of a new partition (segment)</p>
<p>insert into newsales values (11160,17450,to_date(&#8217;01-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;I',9999,19,798) ;<br />
insert into newsales values (1340,33710,to_date(&#8217;02-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;S',9999,16,1264) ;<br />
insert into newsales values (25270,65880,to_date(&#8217;05-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;I',9999,5,210) ;<br />
insert into newsales values (1615,73480,to_date(&#8217;05-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;I',9999,8,96) ;<br />
insert into newsales values (1900,84910,to_date(&#8217;06-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;I',9999,42,378) ;<br />
insert into newsales values (8085,37900,to_date(&#8217;09-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;S',9999,1,68) ;<br />
insert into newsales values (755,26590,to_date(&#8217;09-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;I',9999,11,132) ;<br />
insert into newsales values (10,68060,to_date(&#8217;09-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;P',9999,28,4900) ;<br />
insert into newsales values (13425,109310,to_date(&#8217;10-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;I',9999,1,68) ;<br />
insert into newsales values (1955,65190,to_date(&#8217;10-jan-2005&#8242;,&#8217;dd-mon-yyyy&#8217;),&#8217;S',9999,28,1512) ;</p>
<p>commit<br />
/</p>
<p>Check again:</p>
<p>select partition_name, high_value<br />
from user_tab_partitions<br />
where table_name = &#8216;NEWSALES&#8217;<br />
order by partition_position<br />
/</p>
<p>PARTITION_NAME            HIGH_VALUE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
P_BEFORE_1_JAN_2005       TO_DATE(&#8217; 2005-01-01 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)<br />
SYS_P41                   TO_DATE(&#8217; 2005-01-02 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)<br />
SYS_P42                   TO_DATE(&#8217; 2005-01-03 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)<br />
SYS_P43                   TO_DATE(&#8217; 2005-01-06 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)<br />
SYS_P44                   TO_DATE(&#8217; 2005-01-07 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)<br />
SYS_P45                   TO_DATE(&#8217; 2005-01-10 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)<br />
SYS_P46                   TO_DATE(&#8217; 2005-01-11 00:00:00&#8242;, &#8216;SYYYY-MM-DD HH24:MI:SS&#8217;, &#8216;NLS_CALENDAR=GREGORIAN&#8217;)</p>
<p>7 rows selected.</p>
<p>Wow ==> Automatic Interval Partitioning Works Fine.</p>
<p>But when people insert strange values you might end up with a lot of partitions you don&#8217;t really want to have.<br />
So does this really help the lazydba?</p>
<p>#######<br />
Conclusion: In 11g finally Automatic Interval Partitioning is available.<br />
No more full overflow partitions, and DBA&#8217;s who forgot to create a new partition on time.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-8-interval-partitioning/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Blogging about 11g - Part 5 - SQL Plan Management</title>
		<link>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-5-sql-plan-management/</link>
		<comments>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-5-sql-plan-management/#comments</comments>
		<pubDate>Mon, 20 Aug 2007 10:46:21 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Oracle Infrastructure]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/blogging-about-11g-part-5-sql-plan-management</guid>
		<description><![CDATA[The new 11g SQL plan management feature enables the optimizer to maintain a history of
execution plans for a SQL statement. Using the execution plan history the optimizer is
able to detect a new plan representing a plan change for a SQL statement. When the
optimizer detects a new plan, it stores the new plan and marks it [...]]]></description>
			<content:encoded><![CDATA[<p>The new 11g SQL plan management feature enables the optimizer to maintain a history of<br />
execution plans for a SQL statement. Using the execution plan history the optimizer is<br />
able to detect a new plan representing a plan change for a SQL statement. When the<br />
optimizer detects a new plan, it stores the new plan and marks it for performance<br />
evaluation and uses the old plan. The optimizer uses the new plan only after its performance<br />
 is verified to be better than that of the old plan. With this feature performance regressions<br />
caused by execution plan changes can be prevented.</p>
<p>SQL plan management is a preventative mechanism that records and evaluates the execution plans of SQL statements over time, and builds SQL plan baselines composed of a set of existing plans known to be efficient. The SQL plan baselines are then used to preserve performance of corresponding SQL statements, regardless of changes occurring in the system.</p>
<p>TEST STEPS<br />
1-Capturing SQL Plan Baselines<br />
2-Selecting SQL Plan Baselines<br />
3-Evolving SQL Plan Baselines</p>
<p>Step 1) You can use Automatic or Manual Plan Capture</p>
<p>1a) Automatic Plan Capture<br />
To enable automatic plan capture, set the OPTIMIZER_CAPTURE_SQL_PLAN_BASELINES initialization parameter to TRUE.<br />
By default, this parameter is set to FALSE.</p>
<p>When automatic plan capture is enabled, the system automatically creates and maintains the plan history for SQL statements using information provided by the optimizer. The plan history will include relevant information used by the optimizer to reproduce an execution plan, such as the SQL text, outline, bind variables, and compilation environment.</p>
<p>The initial plan generated for a SQL statement is marked as accepted for use by the optimizer, and represents both the plan history and the SQL plan baseline. All subsequent plans will be included in the plan history, and those plans that are verified not to cause performance regressions will be added to the SQL plan baseline during the SQL plan baseline evolution phase.</p>
<p>1b) Manual Plan Loading<br />
Another way to create SQL plan baselines is by manually loading existing plans for a<br />
set of SQL statements as SQL plan baselines. The manually loaded plans are not<br />
verified for performance, but are added as accepted plans to existing or new SQL plan<br />
baselines. Manual plan loading can be used in conjunction with or as an alternative to<br />
automatic plan capture. Manual plan loading can be performed by:<br />
-Loading Plans from SQL Tuning Sets and AWR Snapshots<br />
-Loading Plans from the Cursor Cache</p>
<p>To load plans from a SQL Tuning Set, use the LOAD_PLANS_FROM_SQLSET function of the DBMS_SPM package:</p>
<p>I used my SQL Tuning Set named SQLSET2 (See blogging about 11g - Part 2 SQL Replay).</p>
<p>declare<br />
xx PLS_INTEGER;<br />
begin<br />
xx :=DBMS_SPM.LOAD_PLANS_FROM_SQLSET(sqlset_name => &#8216;SQLSET2&#8242;);<br />
end<br />
;<br />
/</p>
<p>PL/SQL procedure successfully completed.</p>
<p>To load plans from Automatic Workload Repository (AWR), load the plans stored in AWR snapshots into a SQL Tuning Set before using the LOAD_PLANS_FROM_SQLSET function. Loading Plans from the Cursor Cache To load plans from the cursor cache, use the LOAD_PLANS_FROM_CURSOR_CACHE function of the DBMS_SPM package.</p>
<p>To load plans from the cursor cache look for the correct sql_id and do:</p>
<p>declare<br />
YY PLS_INTEGER;<br />
BEGIN<br />
YY :=DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id=>&#8217;40b1ud5f95&#215;9p&#8217;);<br />
end;<br />
/</p>
<p>PL/SQL procedure successfully completed.</p>
<p>Checking the sql_id&#8217;s can be done with:</p>
<p>select user_name, hash_value, sql_id, sql_text from v$open_cursor<br />
where user_name =&#8217;SCOTT&#8217; and hash_value like &#8216;1553134901&#8242;<br />
/</p>
<p>USER_NAME                      HASH_VALUE SQL_ID<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;-<br />
SQL_TEXT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
SCOTT                          1553134901 40b1ud5f95&#215;9p<br />
select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;</p>
<p>As you can see If tested with the SCOTT user. It has ran the query &#8220;select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217; &#8221;<br />
a few times, so it is in the cursor cache.</p>
<p>To be able to see captured baselines I altered scott&#8217;s session with:</p>
<p>alter session set optimizer_capture_sql_plan_baselines = TRUE;</p>
<p>Re-executed the query a few times and then checked if there where any SQL Plan Baselines.</p>
<p>SQL> select sql_handle, plan_name, enabled, accepted, fixed from dba_sql_plan_baselines;</p>
<p>SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212; &#8212; &#8212;<br />
SYS_SQL_02a86218930bbb20       SYS_SQL_PLAN_930bbb20b349b57a  YES YES NO<br />
SYS_SQL_0542ffe08bcc9712       SYS_SQL_PLAN_8bcc97123fa57a94  YES YES NO<br />
SYS_SQL_07b3f7d6dc71eb16       SYS_SQL_PLAN_dc71eb1660a8367e  YES YES NO<br />
SYS_SQL_115024ccba5e158c       SYS_SQL_PLAN_ba5e158c9d3031ef  YES YES NO<br />
SYS_SQL_1278d3e5ddb954cd       SYS_SQL_PLAN_ddb954cd3b22d354  YES YES NO<br />
SYS_SQL_294c437e331fa51f       SYS_SQL_PLAN_331fa51f7f6c12a1  YES YES NO<br />
SYS_SQL_4a0d0d05997d40be       SYS_SQL_PLAN_997d40be68603fd4  YES YES NO<br />
SYS_SQL_683ffb98878e87db       SYS_SQL_PLAN_878e87db68603fd4  YES YES NO<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc3ebce39a4  YES YES NO<br />
SYS_SQL_ab81ddd2fd7e0a66       SYS_SQL_PLAN_fd7e0a6652c669e9  YES YES NO<br />
SYS_SQL_b5a286368feca840       SYS_SQL_PLAN_8feca84068603fd4  YES YES NO<br />
SYS_SQL_cf8bfba0667f84ff       SYS_SQL_PLAN_667f84ff0377d7c1  YES YES NO</p>
<p>12 rows selected.</p>
<p>==> Our query from SCOTT is: SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc3ebce39a4  YES YES NO</p>
<p>I found the PLAN_NAME named SYS_SQL_PLAN_43f76bc3ebce39a4  by using: set autotrace on</p>
<p>SQL> select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;<br />
  2  ;</p>
<p>ENAME<br />
&#8212;&#8212;&#8212;-<br />
BLAKE</p>
<p>Execution Plan<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     6 |     3   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - filter(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>SQL> /</p>
<p>ENAME<br />
&#8212;&#8212;&#8212;-<br />
BLAKE</p>
<p>Execution Plan<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     6 |     3   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - filter(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Note<br />
&#8212;&#8211;<br />
   - SQL plan baseline &#8220;SYS_SQL_PLAN_43f76bc3ebce39a4&#8243; used for this statement</p>
<p>HERE it is at the bottem.</p>
<p>Using the following command I can create a report for this plan.</p>
<p>select * from table(<br />
dbms_xplan.display_sql_plan_baseline(<br />
plan_name=>&#8217;SYS_SQL_PLAN_43f76bc3ebce39a4&#8242;,<br />
format=>&#8217;basic&#8217;));</p>
<p>PLAN_TABLE_OUTPUT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
SQL handle: SYS_SQL_a987298e43f76bc3<br />
SQL text: select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan name: SYS_SQL_PLAN_43f76bc3ebce39a4<br />
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
| Id  | Operation         | Name |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
|   0 | SELECT STATEMENT  |      |<br />
|   1 |  TABLE ACCESS FULL| EMP  |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>19 rows selected.</p>
<p>YOU can see the Origin: AUTO-CAPTURE. I still have some issues doing a manual capture?!</p>
<p>I can also report on this query using the SQL_HANDLE that I have found in dba_sql_plan_baselines.</p>
<p>select * from table(<br />
dbms_xplan.display_sql_plan_baseline(<br />
sql_handle=>&#8217;SYS_SQL_a987298e43f76bc3&#8242;,<br />
format=>&#8217;basic&#8217;));</p>
<p>PLAN_TABLE_OUTPUT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
SQL handle: SYS_SQL_a987298e43f76bc3<br />
SQL text: select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan name: SYS_SQL_PLAN_43f76bc3ebce39a4<br />
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
| Id  | Operation         | Name |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
|   0 | SELECT STATEMENT  |      |<br />
|   1 |  TABLE ACCESS FULL| EMP  |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>19 rows selected.</p>
<p>It shows the same result.</p>
<p>Note that the FORMAT string determines what information stored in the plan<br />
displayed. One of three format values (&#8217;BASIC&#8217;, &#8216;TYPICAL&#8217;, &#8216;ALL&#8217;)<br />
can be used, each representing a common use case.</p>
<p>Let report all, then we get:</p>
<p>select * from table(<br />
dbms_xplan.display_sql_plan_baseline(<br />
sql_handle=>&#8217;SYS_SQL_a987298e43f76bc3&#8242;,<br />
format=>&#8217;all&#8217;));</p>
<p>PLAN_TABLE_OUTPUT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
SQL handle: SYS_SQL_a987298e43f76bc3<br />
SQL text: select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan name: SYS_SQL_PLAN_43f76bc3ebce39a4<br />
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     6 |     3   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Query Block Name / Object Alias (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>   1 - SEL$1 / E@SEL$1</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - filter(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Column Projection Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>   1 - &#8220;E&#8221;.&#8221;ENAME&#8221;[VARCHAR2,10]</p>
<p>34 rows selected.</p>
<p>AHA we get some more information. Especially the Column Projection Information is interesting.<br />
It shows which column is in the where clause, and with an index this query can be speeded up.</p>
<p>Lets tune this &#8220;Full Table Scanned&#8221; query.</p>
<p>SQL> create index EMP_NAME on EMP(ename);</p>
<p>Index created.</p>
<p>SQL> select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;;</p>
<p>ENAME<br />
&#8212;&#8212;&#8212;-<br />
BLAKE</p>
<p>Execution Plan<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     6 |     3   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - filter(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Note<br />
&#8212;&#8211;<br />
   - SQL plan baseline &#8220;SYS_SQL_PLAN_43f76bc3ebce39a4&#8243; used for this statement</p>
<p>No Index is used. SO THIS IS A FEATURE TO RECON WITH.</p>
<p>Step 2) Selecting SQL Plan Baselines<br />
The DBA first has to checkout the available SQL PLans ..</p>
<p>SQL> select sql_handle, plan_name, enabled, accepted, fixed from dba_sql_plan_baselines;</p>
<p>SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212; &#8212; &#8212;<br />
SYS_SQL_02a86218930bbb20       SYS_SQL_PLAN_930bbb20b349b57a  YES YES NO<br />
SYS_SQL_0542ffe08bcc9712       SYS_SQL_PLAN_8bcc97123fa57a94  YES YES NO<br />
SYS_SQL_07b3f7d6dc71eb16       SYS_SQL_PLAN_dc71eb1660a8367e  YES YES NO<br />
SYS_SQL_115024ccba5e158c       SYS_SQL_PLAN_ba5e158c9d3031ef  YES YES NO<br />
SYS_SQL_1278d3e5ddb954cd       SYS_SQL_PLAN_ddb954cd3b22d354  YES YES NO<br />
SYS_SQL_181e870c7b6b7300       SYS_SQL_PLAN_7b6b730052c669e9  YES YES NO<br />
SYS_SQL_294c437e331fa51f       SYS_SQL_PLAN_331fa51f7f6c12a1  YES YES NO<br />
SYS_SQL_4a0d0d05997d40be       SYS_SQL_PLAN_997d40be68603fd4  YES YES NO<br />
SYS_SQL_683ffb98878e87db       SYS_SQL_PLAN_878e87db68603fd4  YES YES NO<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc37adb8510  YES NO  NO<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc3ebce39a4  YES YES NO<br />
SYS_SQL_ab81ddd2fd7e0a66       SYS_SQL_PLAN_fd7e0a6652c669e9  YES YES NO<br />
SYS_SQL_b5a286368feca840       SYS_SQL_PLAN_8feca84068603fd4  YES YES NO<br />
SYS_SQL_cf8bfba0667f84ff       SYS_SQL_PLAN_667f84ff0377d7c1  YES YES NO</p>
<p>14 rows selected.</p>
<p>==> Their is an extra PLAN_NAME for our sql_handle : SYS_SQL_a987298e43f76bc3.<br />
It now has an extra NO(t) Accepted plan.</p>
<p>Lets report all again:</p>
<p>select * from table(<br />
dbms_xplan.display_sql_plan_baseline(<br />
sql_handle=>&#8217;SYS_SQL_a987298e43f76bc3&#8242;,<br />
format=>&#8217;all&#8217;));</p>
<p>PLAN_TABLE_OUTPUT<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
SQL handle: SYS_SQL_a987298e43f76bc3<br />
SQL text: select e.ename from scott.emp e where e.ename = &#8216;BLAKE&#8217;<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan name: SYS_SQL_PLAN_43f76bc37adb8510<br />
Enabled: YES     Fixed: NO      Accepted: NO      Origin: AUTO-CAPTURE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Plan hash value: 2061206800</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT |          |     1 |     6 |     1   (0)| 00:00:01 |<br />
|*  1 |  INDEX RANGE SCAN| EMP_NAME |     1 |     6 |     1   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Query Block Name / Object Alias (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>   1 - SEL$1 / E@SEL$1</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - access(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Column Projection Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>   1 - &#8220;E&#8221;.&#8221;ENAME&#8221;[VARCHAR2,10]</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
Plan name: SYS_SQL_PLAN_43f76bc3ebce39a4<br />
Enabled: YES     Fixed: NO      Accepted: YES     Origin: AUTO-CAPTURE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     6 |     3   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Query Block Name / Object Alias (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>   1 - SEL$1 / E@SEL$1</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - filter(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Column Projection Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>   1 - &#8220;E&#8221;.&#8221;ENAME&#8221;[VARCHAR2,10]</p>
<p>63 rows selected.</p>
<p>AHA An index scan gives cost of 1 in stead of 3. It is 3 times cheaper.</p>
<p>Now is the question how to Accept this better plan.</p>
<p>Step 3) Evolving SQL Plan Baselines</p>
<p>SQL> select sql_handle, plan_name, enabled, accepted, fixed from dba_sql_plan_baselines;</p>
<p>SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212; &#8212; &#8212;<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc3ebce39a4  YES NO  NO<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc37adb8510  YES YES NO<br />
&#8230;</p>
<p>The first method is to load plans manually from the cursor cache or a SQL tuning set,<br />
so that the SQL plan baselines are evolved to contain loaded plans as additional accepted plans.</p>
<p>declare<br />
YY PLS_INTEGER;<br />
BEGIN<br />
YY :=DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE(sql_id=>&#8217;40b1ud5f95&#215;9p&#8217;);<br />
end;<br />
/</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> select sql_handle, plan_name, enabled, accepted, fixed from dba_sql_plan_baselines;</p>
<p>SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212; &#8212; &#8212;<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc3ebce39a4  YES YES NO<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc37adb8510  YES YES NO<br />
&#8230;</p>
<p>==> The plan is now accepted!</p>
<p>Now remove the invalid PLAN_NAME (Which did a full Table scan).</p>
<p>The bad plan with the Full Table Scan is:<br />
SYS_SQL_a987298e43f76bc3       SYS_SQL_PLAN_43f76bc3ebce39a4</p>
<p>PURGE_SQL_PLAN_BASELINE as user SYSTEM Works with:</p>
<p>declare<br />
ZZ PLS_INTEGER;<br />
begin<br />
ZZ:= DBMS_SPM.PURGE_SQL_PLAN_BASELINE(sql_handle =>&#8217;SYS_SQL_a987298e43f76bc3&#8242;,plan_name =>&#8217;SYS_SQL_PLAN_43f76bc3ebce39a4&#8242;);<br />
end;<br />
/</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL>  select sql_handle, plan_name, enabled, accepted, fixed from dba_sql_plan_baselines;</p>
<p>SQL_HANDLE                     PLAN_NAME                      ENA ACC FIX<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212; &#8212; &#8212;<br />
SYS_SQL_02a86218930bbb20       SYS_SQL_PLAN_930bbb20b349b57a  YES YES NO<br />
SYS_SQL_b5a286368feca840       SYS_SQL_PLAN_8feca84068603fd4  YES YES NO<br />
SYS_SQL_07b3f7d6dc71eb16       SYS_SQL_PLAN_dc71eb1660a8367e  YES YES NO<br />
SYS_SQL_683ffb98878e87db       SYS_SQL_PLAN_878e87db68603fd4  YES YES NO<br />
SYS_SQL_4a0d0d05997d40be       SYS_SQL_PLAN_997d40be68603fd4  YES YES NO<br />
SYS_SQL_115024ccba5e158c       SYS_SQL_PLAN_ba5e158c9d3031ef  YES YES NO<br />
SYS_SQL_294c437e331fa51f       SYS_SQL_PLAN_331fa51f7f6c12a1  YES YES NO<br />
SYS_SQL_0542ffe08bcc9712       SYS_SQL_PLAN_8bcc97123fa57a94  YES YES NO<br />
SYS_SQL_cf8bfba0667f84ff       SYS_SQL_PLAN_667f84ff0377d7c1  YES YES NO<br />
SYS_SQL_1278d3e5ddb954cd       SYS_SQL_PLAN_ddb954cd3b22d354  YES YES NO<br />
SYS_SQL_ab81ddd2fd7e0a66       SYS_SQL_PLAN_fd7e0a6652c669e9  YES YES NO<br />
SYS_SQL_181e870c7b6b7300       SYS_SQL_PLAN_7b6b730052c669e9  YES YES NO</p>
<p>12 rows selected.</p>
<p>==> The plan has been purged.</p>
<p>The second method to evolve plans is to use the SQL Tuning Advisor, which identifies tuned plans for a set of SQL statements stored in a SQL tuning set. After verifying the performance of a tuned plan, the SQL Tuning Advisor makes a recommendation to accept a SQL profile. Once the SQL profile is accepted, the tuned plan is added to the corresponding SQL plan baseline.</p>
<p>In Oracle Database 11g, an automatically configured task runs the SQL Tuning Advisor during a maintenance window. This automatic SQL tuning task targets high-load SQL statements as identified by the execution performance data collected in the Automatic Workload Repository (AWR) snapshots. The SQL profile recommendations made by the SQL tuning advisor are implemented by the automatic SQL tuning task. Tuned plans are thus automatically added to the SQL plan baselines of the identified high-load SQL statements.</p>
<p>#######<br />
Conclusion: In 11g SQL Plan Management is possible.</p>
<p>The default behaviour is that automatic plan capture is not enabled<br />
(optimizer_capture_sql_plan_baselines is FALSE).</p>
<p>Does work as designed. If you have the right documentation <img src='http://www.bloggingaboutjava.org/cms/wordpress2/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> Associated bug 6010750, wrong documentation. SR Number  6239541.994</p>
<p>Notes:<br />
-Default the purge job waits for 1 year, for UNUSED plans!).<br />
-Disable SQL Plan usage with : optimizer_use_sql_plan_baselines = FALSE. Default is TRUE!<br />
-Stored outlines are deprecated in Oracle Database 11g. Oracle highly recommends migrating existing stored outlines to SQL plan baselines.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/08/blogging-about-11g-part-5-sql-plan-management/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Blogging about 11g - Part 4 - Invisible Indexes</title>
		<link>http://www.bloggingaboutjava.org/2007/07/blogging-about-11g-part-4-invisible-indexes/</link>
		<comments>http://www.bloggingaboutjava.org/2007/07/blogging-about-11g-part-4-invisible-indexes/#comments</comments>
		<pubDate>Fri, 27 Jul 2007 19:30:30 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/blogging-about-11g-part-4-invisible-indexes</guid>
		<description><![CDATA[The 11g Oracle DBA can now apply an invisible performance patch (an Invisible Index)
on a non-performing query on a production system, without any impact on other queries.
Invisible indexes are not considered by the optimizer. These indexes are only used with a hint.
Here is a demo.
SQL> conn scott/tiger
Connected.
SQL> select * from cat;
TABLE_NAME     [...]]]></description>
			<content:encoded><![CDATA[<p>The 11g Oracle DBA can now apply an invisible performance patch (an Invisible Index)<br />
on a non-performing query on a production system, without any impact on other queries.</p>
<p>Invisible indexes are not considered by the optimizer. These indexes are only used with a hint.</p>
<p>Here is a demo.</p>
<p>SQL> conn scott/tiger<br />
Connected.</p>
<p>SQL> select * from cat;</p>
<p>TABLE_NAME                     TABLE_TYPE<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8211;<br />
DEPT                           TABLE<br />
EMP                            TABLE<br />
BONUS                          TABLE<br />
SALGRADE                       TABLE</p>
<p>4 rows selected.</p>
<p>SQL> select index_name from user_indexes;</p>
<p>INDEX_NAME<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
PK_EMP<br />
PK_DEPT</p>
<p>select index_name<br />
,      index_owner<br />
,      table_name<br />
,      column_name<br />
,      column_position cpos<br />
,      column_length clen<br />
from all_ind_columns<br />
where index_name like &#8216;PK%&#8217;<br />
and index_owner = &#8216;SCOTT&#8217;<br />
order by index_name, table_name, cpos;</p>
<p>INDEX_NAME           INDEX_OWNER TABLE_NAME      COLUMN_NAME           CPOS  CLEN<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8211; &#8212;&#8211;<br />
PK_DEPT              SCOTT       DEPT            DEPTNO                   1    22<br />
PK_EMP               SCOTT       EMP             EMPNO                    1    22</p>
<p>SQL> desc emp<br />
 Name                                                              Null?    Type<br />
 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 EMPNO                                                             NOT NULL NUMBER(4)<br />
 ENAME                                                                      VARCHAR2(10)<br />
 JOB                                                                        VARCHAR2(9)<br />
 MGR                                                                        NUMBER(4)<br />
 HIREDATE                                                                   DATE<br />
 SAL                                                                        NUMBER(7,2)<br />
 COMM                                                                       NUMBER(7,2)<br />
 DEPTNO                                                                     NUMBER(2)</p>
<p>NOW THE MAGIC TRICK<br />
&#8211; Has anyone seen Hans Klok (Our Dutch top Magician) in Las Vegas yet?<br />
&#8211; He hired Pamela Anderson as side-kick in his show.</p>
<p>create index EMP_NAME on EMP(ename) invisible;</p>
<p>Index created.</p>
<p>Now test if it is picked up.<br />
SQL> set autotrace on<br />
SQL> select e.ename from emp e where e.ename = &#8216;BLAKE&#8217;<br />
SQL> /</p>
<p>ENAME<br />
&#8212;&#8212;&#8212;-<br />
BLAKE</p>
<p>Execution Plan<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Plan hash value: 3956160932</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT  |      |     1 |     6 |     3   (0)| 00:00:01 |<br />
|*  1 |  TABLE ACCESS FULL| EMP  |     1 |     6 |     3   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - filter(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Statistics<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
          0  recursive calls<br />
          0  db block gets<br />
          8  consistent gets<br />
          0  physical reads<br />
          0  redo size<br />
        423  bytes sent via SQL*Net to client<br />
        416  bytes received via SQL*Net from client<br />
          2  SQL*Net roundtrips to/from client<br />
          0  sorts (memory)<br />
          0  sorts (disk)<br />
          1  rows processed</p>
<p>SQL> select /*+INDEX(e EMP_NAME) */ e.ename from emp e where e.ename = &#8216;BLAKE&#8217;;</p>
<p>ENAME<br />
&#8212;&#8212;&#8212;-<br />
BLAKE</p>
<p>Execution Plan<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Plan hash value: 2061206800</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
| Id  | Operation        | Name     | Rows  | Bytes | Cost (%CPU)| Time     |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
|   0 | SELECT STATEMENT |          |     1 |     6 |     1   (0)| 00:00:01 |<br />
|*  1 |  INDEX RANGE SCAN| EMP_NAME |     1 |     6 |     1   (0)| 00:00:01 |<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>Predicate Information (identified by operation id):<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</p>
<p>   1 - access(&#8221;E&#8221;.&#8221;ENAME&#8221;=&#8217;BLAKE&#8217;)</p>
<p>Statistics<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
          1  recursive calls<br />
          0  db block gets<br />
          2  consistent gets<br />
          0  physical reads<br />
          0  redo size<br />
        423  bytes sent via SQL*Net to client<br />
        416  bytes received via SQL*Net from client<br />
          2  SQL*Net roundtrips to/from client<br />
          0  sorts (memory)<br />
          0  sorts (disk)<br />
          1  rows processed</p>
<p>It really works! We get a reduction from 8 to 2 consistent gets!</p>
<p>Handy information from the data dictionary:</p>
<p>SQL> select index_name , visibility from user_indexes;</p>
<p>INDEX_NAME                     VISIBILITY<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;-<br />
PK_EMP                         VISIBLE<br />
EMP_NAME                       INVISIBLE<br />
PK_DEPT                        VISIBLE</p>
<p>SQL> alter index EMP_NAME visible;</p>
<p>Index altered.</p>
<p>SQL> select index_name , visibility from user_indexes;</p>
<p>INDEX_NAME                     VISIBILITY<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;-<br />
PK_EMP                         VISIBLE<br />
EMP_NAME                       VISIBLE<br />
PK_DEPT                        VISIBLE</p>
<p>#######<br />
Conclusion: In 11g Invisible Indexes seems to work as designed.</p>
<p>You can test adding indexes without impact on current plans!<br />
You can also test the removal of indexes on plans before actually dropping the index!<br />
You can fine tune specific statements when adding one index changes other plans badly.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/07/blogging-about-11g-part-4-invisible-indexes/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Blogging about 11g - Part 3 - Flashback Data Archive a.k.a. Total Recall</title>
		<link>http://www.bloggingaboutjava.org/2007/07/blogging-about-11g-part-3-flashback-data-archive-aka-total-recall/</link>
		<comments>http://www.bloggingaboutjava.org/2007/07/blogging-about-11g-part-3-flashback-data-archive-aka-total-recall/#comments</comments>
		<pubDate>Tue, 24 Jul 2007 06:13:24 +0000</pubDate>
		<dc:creator>Yuri van Buren</dc:creator>
		
		<category><![CDATA[Databases]]></category>

		<category><![CDATA[Oracle Infrastructure]]></category>

		<guid isPermaLink="false">http://www.bloggingaboutoracle.org/archives/blogging-about-11g-part-3-flashback-data-archive-aka-total-recall</guid>
		<description><![CDATA[Flashback Data Archive (track all changes to a record over time).
For flashback data archive you need a tablespace first.
In this demo I have created a tablespace named testarea1
Now I can create a Flashback Archive with:
CREATE FLASHBACK ARCHIVE DEFAULT fla1 TABLESPACE testarea1
QUOTA 10G RETENTION 1 YEAR;
Flashback archive created.
You can Remove the Flashback Archive as well with:
DROP [...]]]></description>
			<content:encoded><![CDATA[<p>Flashback Data Archive (track all changes to a record over time).</p>
<p>For flashback data archive you need a tablespace first.<br />
In this demo I have created a tablespace named testarea1</p>
<p>Now I can create a Flashback Archive with:<br />
CREATE FLASHBACK ARCHIVE DEFAULT fla1 TABLESPACE testarea1<br />
QUOTA 10G RETENTION 1 YEAR;</p>
<p>Flashback archive created.</p>
<p>You can Remove the Flashback Archive as well with:<br />
DROP FLASHBACK ARCHIVE fla1;</p>
<p>Flashback archive dropped.</p>
<p>Note that this leaves the tablespace intact.</p>
<p>After re-creating the Flashback Archive you can test with changing the retention time</p>
<p>SQL> alter flashback archive fla1 modify retention 7 days;<br />
alter flashback archive fla1 modify retention 7 days<br />
                                                *<br />
ERROR at line 1:<br />
ORA-55603: Invalid Flashback Archive command</p>
<p>SQL> alter flashback archive fla1 modify retention 7 day;</p>
<p>Flashback archive altered.</p>
<p>As you can see you have to specify Day NOT Days <img src='http://www.bloggingaboutjava.org/cms/wordpress2/wp-includes/images/smilies/icon_sad.gif' alt=':-(' class='wp-smiley' /> Not very intuitive.</p>
<p>Now lets query the dictionary to check what we have created<br />
SQL> select * from flashback_archive_tablespaces;</p>
<p>FLASHBACK_ARCHIVE_NAME<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
FLASHBACK_ARCHIVE# TABLESPACE_NAME                QUOTA_IN_MB<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
FLA1<br />
                 1 TESTAREA1                      10240</p>
<p>1 row selected.</p>
<p>Now set a table in the flashback arhive mode.</p>
<p>select table_name from dba_tables where owner = &#8216;HR&#8217;<br />
/</p>
<p>TABLE_NAME<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
EMPLOYEES<br />
JOB_HISTORY<br />
JOBS<br />
REGIONS<br />
LOCATIONS<br />
DEPARTMENTS<br />
COUNTRIES</p>
<p>7 rows selected.</p>
<p>alter table hr.employees flashback archive fla1;</p>
<p>Table altered.</p>
<p>Check which tables are in flachback archive mode.</p>
<p>select * from flashback_archived_tables;</p>
<p>TABLE_NAME                     OWNER_NAME                     FLASHBACK_ARCHIVE_NAME<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
EMPLOYEES                      HR                             FLA1</p>
<p>1 row selected.</p>
<p>SQL> select count(*) from hr.employees;</p>
<p>  COUNT(*)<br />
&#8212;&#8212;&#8212;-<br />
       107</p>
<p>1 row selected.</p>
<p>Checked : 19-JUN-2007 20:22:39</p>
<p>SQL> desc hr.employees;<br />
 Name                                            Null?    Type<br />
 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 EMPLOYEE_ID                                     NOT NULL NUMBER(6)<br />
 FIRST_NAME                                               VARCHAR2(20)<br />
 LAST_NAME                                       NOT NULL VARCHAR2(25)<br />
 EMAIL                                           NOT NULL VARCHAR2(25)<br />
 PHONE_NUMBER                                             VARCHAR2(20)<br />
 HIRE_DATE                                       NOT NULL DATE<br />
 JOB_ID                                          NOT NULL VARCHAR2(10)<br />
 SALARY                                                   NUMBER(8,2)<br />
 COMMISSION_PCT                                           NUMBER(2,2)<br />
 MANAGER_ID                                               NUMBER(6)<br />
 DEPARTMENT_ID                                            NUMBER(4)</p>
<p>SQL> select employee_id, salary from hr.employees;</p>
<p>..<br />
        192       4000<br />
        193       3900<br />
        194       3200<br />
        195       2800<br />
        196       3100<br />
        197       3000<br />
        198       2600<br />
        199       2600<br />
        200       4400<br />
        201      13000<br />
        202       6000<br />
        203       6500<br />
        204      10000<br />
        205      12000<br />
        206       8300</p>
<p>107 rows selected.</p>
<p>SQL> update hr.employees set salary = 5000 where salary = 4000;</p>
<p>1 row updated.</p>
<p> &#8211;>      192       5000<br />
        193       3900<br />
        194       3200<br />
        195       2800<br />
        196       3100<br />
        197       3000<br />
        198       2600<br />
        199       2600<br />
        200       4400<br />
        201      13000<br />
        202       6000<br />
        203       6500<br />
        204      10000<br />
        205      12000<br />
        206       8300</p>
<p>107 rows selected.</p>
<p>Checked : 19-JUN-2007 20:29:52</p>
<p>Prompt now see If I can my data back!<br />
SELECT employee_id, salary from hr.employees AS OF<br />
TIMESTAMP TO_TIMESTAMP (&#8217;2007-06-19 20:28:00&#8242;, &#8216;YYYY-MM-DD HH24:MI:SS&#8217;);</p>
<p>        190       2900<br />
        191       2500<br />
==>Cool  192       4000<br />
        193       3900<br />
        194       3200<br />
        195       2800<br />
        196       3100<br />
        197       3000<br />
        198       2600<br />
        199       2600<br />
        200       4400<br />
        201      13000<br />
        202       6000<br />
        203       6500<br />
        204      10000<br />
        205      12000<br />
        206       8300</p>
<p>107 rows selected.</p>
<p>To really test if Oracle does not get this data from the UNDO tablespace you have to test during a longer period.<br />
I wonder how Oracle has tested a retention time of 10 YEAR? I don&#8217;t know. (Did they change the clock on there Server?).</p>
<p>Basically Oracle keeps all the necessary UNDO data in the flashback area.<br />
There is an asynchronous background process called FBDA which does this work.</p>
<p>Check the fla1 area in the dictionary.</p>
<p>select * from dba_extents where tablespace_name = &#8216;TESTAREA1&#8242;<br />
and owner = &#8216;HR&#8217;<br />
/</p>
<p>OWNER<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
SEGMENT_NAME<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
PARTITION_NAME                 SEGMENT_TYPE       TABLESPACE_NAME<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
 EXTENT_ID    FILE_ID   BLOCK_ID      BYTES     BLOCKS RELATIVE_FNO<br />
&#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;- &#8212;&#8212;&#8212;&#8212;<br />
HR<br />
SYS_FBA_TCRV_IDX_67448<br />
                               INDEX              TESTAREA1<br />
         0          6        233      65536          8            6</p>
<p>HR<br />
SYS_FBA_TCRV_67448<br />
HIGH_PART                      TABLE PARTITION    TESTAREA1<br />
         0          6        225      65536          8            6</p>
<p>HR<br />
SYS_FBA_HIST_67448<br />
HIGH_PART                      TABLE PARTITION    TESTAREA1<br />
         0          6        217      65536          8            6</p>
<p>HR<br />
SYS_FBA_DDL_COLMAP_67448<br />
HIGH_PART                      TABLE PARTITION    TESTAREA1<br />
         0          6        209      65536          8            6</p>
<p>SQL> desc hr.SYS_FBA_DDL_COLMAP_67448<br />
 Name                                            Null?    Type<br />
 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 STARTSCN                                                 NUMBER<br />
 ENDSCN                                                   NUMBER<br />
 XID                                                      RAW(8)<br />
 OPERATION                                                VARCHAR2(1)<br />
 COLUMN_NAME                                              VARCHAR2(255)<br />
 TYPE                                                     VARCHAR2(255)<br />
 HISTORICAL_COLUMN_NAME                                   VARCHAR2(255)</p>
<p>SQL> desc hr.SYS_FBA_TCRV_67448<br />
 Name                                            Null?    Type<br />
 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 RID                                                      ROWID<br />
 STARTSCN                                                 NUMBER<br />
 ENDSCN                                                   NUMBER<br />
 XID                                                      RAW(8)<br />
 OP                                                       VARCHAR2(1)</p>
<p>SQL> desc hr.SYS_FBA_HIST_67448<br />
 Name                                            Null?    Type<br />
 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 RID                                                      VARCHAR2(4000)<br />
 STARTSCN                                                 NUMBER<br />
 ENDSCN                                                   NUMBER<br />
 XID                                                      RAW(8)<br />
 OPERATION                                                VARCHAR2(1)<br />
 EMPLOYEE_ID                                              NUMBER(6)<br />
 FIRST_NAME                                               VARCHAR2(20)<br />
 LAST_NAME                                                VARCHAR2(25)<br />
 EMAIL                                                    VARCHAR2(25)<br />
 PHONE_NUMBER                                             VARCHAR2(20)<br />
 HIRE_DATE                                                DATE<br />
 JOB_ID                                                   VARCHAR2(10)<br />
 SALARY                                                   NUMBER(8,2)<br />
 COMMISSION_PCT                                           NUMBER(2,2)<br />
 MANAGER_ID                                               NUMBER(6)<br />
 DEPARTMENT_ID                                            NUMBER(4)</p>
<p>To disable flashback archiving for the table employee do:<br />
ALTER TABLE hr.employees NO FLASHBACK ARCHIVE;</p>
<p>BEWARE of some very STRICT constraints when using Flashback Data Archive.</p>
<p>DDL Statements are Not Allowed on Tables Enabled for Flashback Data Archive<br />
Using any of the following DDL statements on a table enabled for Flashback Data<br />
Archive causes error ORA-55610:<br />
 ALTER TABLE statement that does any of the following:<br />
: Drops, renames, or modifies a column<br />
: Performs partition or subpartition operations<br />
: Converts a LONG column to a LOB column<br />
: Includes an UPGRADE TABLE clause, with or without an INCLUDING DATA clause<br />
 DROP TABLE statement<br />
 RENAME TABLE statement<br />
 TRUNCATE TABLE statement</p>
<p>Lets test:<br />
SQL> truncate table hr.employees;<br />
truncate table hr.employees<br />
                  *<br />
ERROR at line 1:<br />
ORA-55610: Invalid DDL statement on history-tracked table</p>
<p>and:</p>
<p>SQL> alter table hr.employees drop column commision_pct;<br />
alter table hr.employees drop column commision_pct<br />
*<br />
ERROR at line 1:<br />
ORA-55610: Invalid DDL statement on history-tracked table</p>
<p>Looks pretty protected. But is it really handy?</p>
<p>Especially the perform partition operation worries me.<br />
Does this really mean your big compliancy regulated partitioned table cannot be flashback archived?</p>
<p>#######<br />
Conclusion: In 11g Flashback Data Archive is possible.</p>
<p>It seems to work as designed. If you have the right documentation <img src='http://www.bloggingaboutjava.org/cms/wordpress2/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> But investigate the pre-requisites carefully or you really have to call Arnold Schwarzenegger.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.bloggingaboutjava.org/2007/07/blogging-about-11g-part-3-flashback-data-archive-aka-total-recall/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
