<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Striving for Optimal PerformanceStriving for Optimal Performance</title>
	<atom:link href="http://www.antognini.ch/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.antognini.ch</link>
	<description></description>
	<lastBuildDate>Fri, 18 May 2012 11:35:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	
		<item>
		<title>COMMIT_WAIT and COMMIT_LOGGING</title>
		<link>http://www.antognini.ch/2012/04/commit_wait-and-commit_logging/</link>
		<comments>http://www.antognini.ch/2012/04/commit_wait-and-commit_logging/#comments</comments>
		<pubDate>Thu, 05 Apr 2012 06:15:18 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[10gR2]]></category>
		<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1766</guid>
		<description><![CDATA[Recently I used the COMMIT_WAIT and COMMIT_LOGGING parameters for solving (or, better, working around) a problem I faced while optimizing a specific task for one of my customers. Since it was the first time I used them in a production system, I thought to write this post not only to shortly explain the purpose of [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I used the COMMIT_WAIT and COMMIT_LOGGING parameters for solving (or, better, working around) a problem I faced while optimizing a specific task for one of my customers. Since it was the first time I used them in a production system, I thought to write this post not only to shortly explain the purpose of the these two parameters, but also to show a case where it is sensible to use them.</p>
<p>The purpose of the two parameters is the following:</p>
<p><strong>COMMIT_WAIT</strong></p>
<ul>
<li>Simply put this parameter specifies whether a server process that issues a commit waits for the log writer while it writes the redo data in the redo log files. </li>
<li>If it’s set to WAIT, the default value, the server process waits. And, in most situations, this is the best thing to do. </li>
<li>If it’s set to NOWAIT, it doesn’t wait. This means that, in case of a crash just after a commit, the <a href="http://en.wikipedia.org/wiki/ACID#Durability">D</a> of <a href="http://en.wikipedia.org/wiki/ACID">ACID</a> might be violated! Hence, in general, it is not advised to use this value.</li>
<li>If it’s set to FORCE_WAIT the behaviour is similar to WAIT. The only difference is that settings at a lower level are ignored. In other words, if it is set at the system level it overrides the setting at the session and transaction level. If it’s set at session level it overrides the setting at the transaction level.</li>
</ul>
<p><strong>COMMIT_LOGGING</strong></p>
<ul>
<li>Simply put this parameter specifies whether the log writer writes redo data in batches.</li>
<li>If it’s set to IMMEDIATE, the default value, it basically performs a write operation for each commit.</li>
<li>If it’s set to BATCH, it writes redo data in batches. Since with this value less but larger write operations might be performed, in case of small transactions the log writer should be able to write the redo data in a more efficient way.  </li>
</ul>
<p>Note that in 10.2, the version that introduced these features, there is a single parameter (COMMIT_WRITE) to control them. For example, it is possible to set it to &#8220;NOWAIT, BATCH&#8221;.</p>
<p>To illustrates how these two parameters work I wrote two scripts: <a href="/images/commit.sh">commit.sh</a> and <a href="/images/commit.sql">commit.sql</a>. Their purpose is to show the number of times specific system calls are executed by the log writer and a server process that executes the following PL/SQL block:</p>
<pre>DECLARE
  l_dummy INTEGER;
BEGIN
  FOR i IN 1..1000
  LOOP
    INSERT INTO t VALUES (i, rpad('*',100,'*'));
    COMMIT;
    SELECT count(*) INTO l_dummy FROM dual;
  END LOOP;
END;</pre>
<p>The two system calls I was interested in were the following:</p>
<ul>
<li>semtimedop(2): simply put this one is used by the server process to wait for the log writer</li>
<li>io_submit(2): simply put this one is used by the log writer to write redo data in the redo log files</li>
</ul>
<p>Let’s have a look the output generated by the scripts for three particular cases:</p>
<ul>
<li><strong>COMMIT_WAIT = WAIT and COMMIT_LOGGING = IMMEDIATE</strong>: Notice that the server process executes 1005 times semtimedop(2) and that the log writer executes 1016 times io_submit(2). In other words, for both of them the number of executions is approximately the number of commits performed by the PL/SQL block.</li>
</ul>
<pre>   oracle@helicon:~/commit/ [DBM11203] ./commit.sh chris ian wait immediate 2> /dev/null

   ***** Server Process *****

   % time     seconds  usecs/call     calls    errors syscall
   ------ ----------- ----------- --------- --------- ----------------
   100.00    0.069561          69      1005         1 semtimedop
   ------ ----------- ----------- --------- --------- ----------------
   100.00    0.069561                  1005         1 total

   ***** Log Writer *****

   % time     seconds  usecs/call     calls    errors syscall
   ------ ----------- ----------- --------- --------- ----------------
   100.00    0.013919          14      1016           io_submit
   ------ ----------- ----------- --------- --------- ----------------
   100.00    0.013919                  1016           total</pre>
<ul>
<li><strong>COMMIT_WAIT = NOWAIT and COMMIT_LOGGING = IMMEDIATE</strong>: Notice that, for the server process, the executions of semtimedop(2) dropped to 5. No noticeable difference is observable for the log writer.</li>
</ul>
<pre>oracle@helicon:~/commit/ [DBM11203] ./commit.sh chris ian nowait immediate 2> /dev/null

  ***** Server Process *****

  % time     seconds  usecs/call     calls    errors syscall
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.002195         439         5         1 semtimedop
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.002195                     5         1 total

  ***** Log Writer *****

  % time     seconds  usecs/call     calls    errors syscall
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.010073          10      1015           io_submit
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.010073                  1015           total</pre>
<ul>
<li><strong>COMMIT_WAIT = NOWAIT and COMMIT_LOGGING = BATCH</strong>: Notice that this time not only the number of executions to io_submit(2) dropped to 15, but, in total, much less time was spent for writing the redo data (10*1015 >> 36*15).
</li>
</ul>
<pre>   oracle@helicon:~/commit/ [DBM11203] ./commit.sh chris ian nowait batch 2> /dev/null

  ***** Server Process *****

  % time     seconds  usecs/call     calls    errors syscall
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.002132         533         4         1 semtimedop
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.002132                     4         1 total

  ***** Log Writer *****

  % time     seconds  usecs/call     calls    errors syscall
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.000533          36        15           io_submit
  ------ ----------- ----------- --------- --------- ----------------
  100.00    0.000533                    15           total</pre>
<p>Now that I explained what the purpose of these parameters is, let me describe a case where I successfully used them.</p>
<p>Few weeks ago one of my customers migrated its DMS to a new version. During the migration data had to be moved from one database to another. Unfortunately the migration code was written to process data <a href="http://tkyte.blogspot.com/2006/10/slow-by-slow.html">slow by slow</a>. Hence, to speed up the processing, parallelization was added to the picture.</p>
<p>The following chart (you can click on it to increase its size) shows the load generated by 20 parallel processes with default values for COMMIT_WAIT and COMMIT_LOGGING. With the default configutation the system was able to process about 1000 “objects” per second. As you can see there were a lot of waits related to the commit wait class.</p>
<p><a href="/images/20120404-img1.jpg" rel="lightbox[em]" title="COMMIT_WAIT and COMMIT_LOGGING"><img id="exeplan" src="/images/20120404-img1.jpg" alt="Database load (20 parallel processes; COMMIT_WAIT WAIT; COMMIT_LOGGING = IMMEDIATE)" width="550px" /></a></p>
<p>Since this was a controlled processing using COMMIT_WAIT was not considered a problem. So, we tested the very same load with COMMIT_WAIT set to NOWAIT and COMMIT_LOGGING set to BATCH. The throughput increased to about 1200 “object” per second. In other words, not dramatically. But, more importantly, as the following chart shows almost all waits in the commit wait class disappeared. This was very important because without that serialization taking place we were able to increase the number of parallel processes.</p>
<p><a href="/images/20120404-img2.jpg" rel="lightbox[em]" title="COMMIT_WAIT and COMMIT_LOGGING"><img id="exeplan" src="/images/20120404-img2.jpg" alt="Database load (20 parallel processes; COMMIT_WAIT NOWAIT; COMMIT_LOGGING = BATCH)" width="550px" /></a></p>
<p>The following chart shows the load generated by 50 parallel processes. Again, almost no wait related to commits. With 50 processes the system was able to process about 2300 “objects” per second.</p>
<p><a href="/images/20120404-img3.jpg" rel="lightbox[em]" title="COMMIT_WAIT and COMMIT_LOGGING"><img id="exeplan" src="/images/20120404-img3.jpg" alt="Database load (50 parallel processes; COMMIT_WAIT NOWAIT; COMMIT_LOGGING = BATCH)" width="550px" /></a></p>
<p>In summary, COMMIT_WAIT and COMMIT_LOGGING are not commonly used parameters but, in some specific situations, using them it might be beneficial to avoid wait events related to commits.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2012/04/commit_wait-and-commit_logging/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Analysing Row Lock Contention with LogMiner</title>
		<link>http://www.antognini.ch/2012/03/analysing-row-lock-contention-with-logminer/</link>
		<comments>http://www.antognini.ch/2012/03/analysing-row-lock-contention-with-logminer/#comments</comments>
		<pubDate>Mon, 12 Mar 2012 06:53:00 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[10gR1]]></category>
		<category><![CDATA[10gR2]]></category>
		<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>
		<category><![CDATA[LogMiner]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1756</guid>
		<description><![CDATA[Recently I had to analyse a row lock contention problem that can be illustrated by the following test case: A session (let’s call it #1) creates a table and inserts a row into it (note that “n” is the primary key of the table): SQL> CREATE TABLE t (n NUMBER PRIMARY KEY); SQL> VARIABLE n [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I had to analyse a row lock contention problem that can be illustrated by the following test case:</p>
<ul>
<li>A session (let’s call it #1) creates a table and inserts a row into it (note that “n” is the primary key of the table):</li>
</ul>
<pre>SQL> CREATE TABLE t (n NUMBER PRIMARY KEY);

SQL> VARIABLE n NUMBER

SQL> execute :n := 1

SQL> INSERT INTO t VALUES (:n);</pre>
<ul>
<li>Another session (let’s call it #2) inserts the same data into the same table:</li>
</ul>
<pre>SQL> VARIABLE n NUMBER

SQL> execute :n := 1

SQL> INSERT INTO t VALUES (:n);</pre>
<ul>
<li>Since session #1 did not commit and that session #2 inserted a row with the same primary key, session #2 is blocked waiting for session #1 to either commit or rollback:</li>
</ul>
<pre>SQL> SELECT sid, blocking_session, event, sql_text
  2  FROM v$session LEFT OUTER JOIN v$sqlarea USING (sql_id)
  3  WHERE nvl(blocking_session,sid) IN (SELECT holding_session FROM dba_blockers);

       SID BLOCKING_SESSION EVENT                          SQL_TEXT
---------- ---------------- ------------------------------ ------------------------------
       130                  SQL*Net message from client
       197              130 enq: TX - row lock contention  INSERT INTO t VALUES (:n)</pre>
<p>It goes without saying that in such a case the problem is the application that tried to insert two rows with the same primary key. In the real case the primary key was a natural key, not a surrogate key generated through a sequence. To help the developers troubleshoot the problem it was therefore necessary to know the actual value of the bind variable used for the two inserts. Unfortunately this information is stored in the PGA of the server processes and, therefore, it is not directly accessible. In addition I started investigating the problem only a couple of hours after the contention began and, therefore, also a view like V$SQL_BIND_CAPTURE is of no use.</p>
<p>As a result I decided to mine the archived redo logs to find the information I was looking for. Here is what I did:</p>
<ul>
<li>Find out the XID of the transaction holding the row lock:</li>
</ul>
<pre>SQL> SELECT t.xidusn, t.xidslot, t.xidsqn, t.start_time, t.start_scn
  2  FROM v$transaction t JOIN v$session s ON t.addr = s.taddr
  3  WHERE s.sid = 130;

    XIDUSN    XIDSLOT     XIDSQN START_TIME            START_SCN
---------- ---------- ---------- -------------------- ----------
         7         12       1049 03/09/12 07:10:25       1462388</pre>
<ul>
<li>Find out which archived redo log contains the first redo records of that transaction:</li>
</ul>
<pre>SQL> SELECT name
  2  FROM v$archived_log
  3  WHERE 1462388 BETWEEN first_change# AND next_change# - 1;

NAME
-----------------------------------------------------------------------------------------------
/u00/app/oracle/fast_recovery_area/DBA112/archivelog/2012_03_09/o1_mf_1_94_7om7qzdx_.arc</pre>
<ul>
<li>Start LogMiner:</li>
</ul>
<pre>SQL> EXECUTE dbms_logmnr.add_logfile(logfilename=>'/u00/app/oracle/fast_recovery_area/DBA112/archivelog/2012_03_09/o1_mf_1_94_7om7qzdx_.arc')

SQL> EXECUTE dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog)</pre>
<ul>
<li>Extract the redo information of the operations performed by the transaction holding the row lock and, therefore, finding that the value of the bind variable was “1”:</li>
</ul>
<pre>SQL> SELECT sql_redo
  2  FROM v$logmnr_contents
  3  WHERE xidusn = 7
  4  AND xidslt = 12
  5  AND xidsqn = 1049;

SQL_REDO
--------------------------------------------------------------------------------
set transaction read write;
insert into "CHRIS"."T"("N") values ('1');</pre>
<ul>
<li>Stop LogMiner</li>
</ul>
<pre>SQL> EXECUTE dbms_logmnr.end_logmnr</pre>
<p>In conclusion, even though mining (archived) redo logs for extracting the value of bind variables is probably not the most typical use of LogMiner, it works well. Therefore, do not forget this possibility if you have to do it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2012/03/analysing-row-lock-contention-with-logminer/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Index Scan with Filter Predicate Based on a Subquery</title>
		<link>http://www.antognini.ch/2012/02/index-scan-with-filter-predicate-based-on-a-subquery/</link>
		<comments>http://www.antognini.ch/2012/02/index-scan-with-filter-predicate-based-on-a-subquery/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 21:36:58 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[10gR2]]></category>
		<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Query Optimizer]]></category>
		<category><![CDATA[TOP]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1705</guid>
		<description><![CDATA[Most execution plans can be interpreted by following few basic rules (in TOP, Chapter 6, I provide such a list of rules). Nevertheless, there are some special cases. One of them is when an index scan, in addition to the access predicate, has a filter predicate applying a subquery. The following execution plan, taken from [...]]]></description>
			<content:encoded><![CDATA[<p>Most execution plans can be interpreted by following few basic rules (in TOP, Chapter 6, I provide such a list of rules). Nevertheless, there are some special cases. One of them is when an index scan, in addition to the access predicate, has a filter predicate applying a subquery.</p>
<p>The following execution plan, taken from Enterprise Manager 11.2, is an example (click on the image to increase its size):<br />
<a href="/images/ep20120206.jpg" rel="lightbox" title="Index Scan with Filter Predicate Based on a Subquery"><img id="exeplan" src="/images/ep20120206.jpg" alt="Execution Plan" width="550px" /></a><br />
Notes:</p>
<ul>
<li>According to the order column the first operation being executed is the scan of the <code>I2</code> index. Unfortunately this is wrong. In fact the first operation being executed is the scan of the <code>I1</code> index. This is a bug in Enterprise Manager. I wanted to show you this example to demonstrate that not only for us it might be difficult to correctly interpret an execution plan <img src='http://www.antognini.ch/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </li>
<li>The filter predicate <code>IS NOT NULL</code> is also wrong. This is not a bug, however. It is a limitation in the current implementation. The problem is that in some cases the <code>V$SQL_PLAN</code> and <code>V$SQL_PLAN_STATISTICS_ALL</code> views are not able to show all the necessary details.</li>
</ul>
<p>Without seeing the query on which this execution plan is based, it is not obvious at all to know what’s going on. So, here is the query:</p>
<pre>SELECT *
FROM t1
WHERE n1 = 8
AND n2 IN (SELECT t2.n1 FROM t2, t3 WHERE t2.id = t3.id AND t3.n1 = <img src='http://www.antognini.ch/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /> </pre>
<p>Based on the query it is essential to point out that the access predicate <code>"T2"."N1"=:B1</code> cannot be evaluated and, therefore, the scan of the <code>I2</code> index cannot be carried out, without having a value passed through the B1 bind variable. In other words, without knowing the value of <code>T1.N2</code>.</p>
<p>To describe how this execution plan is carried out, let’s have a look to the information provided by the <code>DBMS_XPLAN.DISPLAY</code> function (which does not expose the limitation related to the filter predicate).</p>
<pre>-----------------------------------------------
| Id  | Operation                      | Name |
-----------------------------------------------
|   0 | SELECT STATEMENT               |      |
|   1 |  TABLE ACCESS BY INDEX ROWID   | T1   |
|*  2 |   INDEX RANGE SCAN             | I1   |
|   3 |    NESTED LOOPS                |      |
|   4 |     TABLE ACCESS BY INDEX ROWID| T2   |
|*  5 |      INDEX RANGE SCAN          | I2   |
|*  6 |     TABLE ACCESS BY INDEX ROWID| T3   |
|*  7 |      INDEX RANGE SCAN          | I3   |
-----------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("N1"=8)
    filter( EXISTS (SELECT /*+ LEADING ("T2" "T3") USE_NL ("T3") INDEX
           ("T3" "I3") INDEX_RS_ASC ("T2" "I2") */ 0 FROM "T3" "T3","T2" "T2" WHERE
           "T2"."N1"=:B1 AND "T3"."N1"=8 AND "T2"."ID"="T3"."ID"))
5 - access("T2"."N1"=:B1)
6 - filter("T2"."ID"="T3"."ID")
7 - access("T3"."N1"=8)</pre>
<p>The operations are carried out as follows:</p>
<ol>
<li>Operation 2 applies the access predicate <code>"N1"=8</code> by scanning the <code>I1</code> index.</li>
<li>For each key returned by the previous scan, the subquery is executed once. Note that the subquery carries out a nested loop. While the outer loop accesses the <code>T2</code> table, the inner loop accesses the <code>T3</code> table. </li>
<li>The first operation of the outer loop is operation 5. It applies the access predicate <code>"T2"."N1"=:B1</code> by scanning the <code>I2</code> index. Based on the rowid returned by the index access the <code>T2</code> table is accessed (operation 4).</li>
<li>For each row returned by the outer loop, the inner loop is executed once. The first operation of the inner loop is operation 7. It applies the access predicate <code>"T3"."N1"=8</code> by scanning the <code>I3</code> index. Based on the rowid returned by the index access the <code>T3</code> table is accessed (operation 6) and the filter predicate <code>"T2"."ID"="T3"."ID"</code> (the join condition) is applied. By the way, it is interesting to notice that, contrary to the join condition is <em>not</em> applied as an access predicate, as it usually happens.</li>
<li>If the subquery returns a row, the rowid returned by operation 2 can be used to access the <code>T1</code> table (operation 1). The row extracted from this operation is sent to the caller.</li>
</ol>
<p>All in all, this is a very special execution plan&#8230;</p>
<p>In summary, be careful when you see an index scan with a filter predicate applying a subquery. The execution plan might not be carried out as you expect at first sight. It is also essential to point out that in such a case the predicate information is essential to fully understand what’s going on.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2012/02/index-scan-with-filter-predicate-based-on-a-subquery/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Ad: The Oracle Query Optimizer 2-Day Seminar</title>
		<link>http://www.antognini.ch/2011/12/ad-the-oracle-query-optimizer-two-day-seminar/</link>
		<comments>http://www.antognini.ch/2011/12/ad-the-oracle-query-optimizer-two-day-seminar/#comments</comments>
		<pubDate>Sat, 17 Dec 2011 23:42:45 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[Query Optimizer]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[TOP]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1689</guid>
		<description><![CDATA[The 31st of January and 1st of February 2012 I will present a 2-day seminar about the Oracle query optimizer in Ballerup (DK). The event is organized by Miracle A/S. The content, which is based on the chapters 2, 4, 5, 6, 9 and 10 of my book, is the following: Chapter 1 describes the [...]]]></description>
			<content:encoded><![CDATA[<p>The 31st of January and 1st of February 2012 I will present a 2-day seminar about the Oracle query optimizer in Ballerup (DK). The event is organized by <a href="http://www.miracleas.dk/">Miracle A/S</a>. The content, which is based on the chapters 2, 4, 5, 6, 9 and 10 of <a href="/top">my book</a>, is the following:</p>
<ul>
<li>Chapter 1 describes the life cycle of SQL statements and when the database engine can share cursors.</li>
<li>Chapter 2 describes the aim and architecture of the query optimizer.</li>
<li>Chapter 3 and 4 discuss the statistics used by the query optimizer to carry out its work.</li>
<li>Chapter 5 describes the initialization parameters influencing the behavior of the query optimizer and how to set them.</li>
<li>Chapter 6 outlines different methods of obtaining execution plans, as well as how to read them and recognize inefficient ones.</li>
<li>Chapter 7 describes how to take advantage of available access structures in order to access data stored in a single table efficiently.</li>
<li>Chapter 8 goes beyond accessing a single table, by describing how to join data from several tables together.</li>
</ul>
<p>The <a href="http://antognini.ch/downloads/Miracle_TheOracleQueryOptimizer_20110131.pdf">flyer</a> and this page provide detailed information about the seminar.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/12/ad-the-oracle-query-optimizer-two-day-seminar/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Challenges and Chances of the 11g Query Optimizer</title>
		<link>http://www.antognini.ch/2011/12/challenges-and-chances-of-the-11g-query-optimizer/</link>
		<comments>http://www.antognini.ch/2011/12/challenges-and-chances-of-the-11g-query-optimizer/#comments</comments>
		<pubDate>Mon, 12 Dec 2011 09:59:52 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Indexes]]></category>
		<category><![CDATA[Object Statistics]]></category>
		<category><![CDATA[Query Optimizer]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[System Statistics]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1665</guid>
		<description><![CDATA[Challenges and Chances of the 11g Query Optimizer is the name of a presentation I gave at several events (e.g. Trivadis Performance Days, Oracle OpenWorld, DOAG Konferenz, UKOUG Conference) throughout 2011. Its abstract is the following: With every new release, the query optimizer is enhanced. Oracle Database 11g Release 1 and Release 2 are no [...]]]></description>
			<content:encoded><![CDATA[<p><em>Challenges and Chances of the 11g Query Optimizer</em> is the name of a presentation I gave at several events (e.g. Trivadis Performance Days, Oracle OpenWorld, DOAG Konferenz, UKOUG Conference) throughout 2011. Its abstract is the following:</p>
<blockquote><p>With every new release, the query optimizer is enhanced. Oracle Database 11g Release 1 and Release 2 are no exception to the rule. Specifically, they introduce key improvements in the following areas: indexing, optimization techniques, object statistics and plan stability. The aim of this presentation is to review the new features from a practical point of view as well as to point out challenges related to them. In other words, to let you know what you can expect from the query optimizer when you upgrade to Oracle Database 11g.</p></blockquote>
<p>The aim of this short post is to point out that I made available the current version of the slides and all the scripts that go with them <a href="/publications/">here</a>.</p>
<p>The structure of the presentation (incl. a reference to the available scripts) is the following:</p>
<ul>
<li>Observations
<ul>
<li>Number of Query Optimizer Parameters by Release</li>
<li>Number of Query Optimizer Bugs Fixed by Patchset</li>
</ul>
</li>
<li>Indexing
<ul>
<li>Invisible Indexes (ex_invisible_index.sql)</li>
<li>Index Support for Linguistic LIKE (ex_linguistic_like.sql)</li>
<li>INDEX REBUILD and Statistics History (ex_index_rebuild.sql)</li>
</ul>
</li>
<li>Optimization Techniques
<ul>
<li>Full Outer Join (ex_full_outer_join.sql)</li>
<li>Join-Filter Pruning (ex_join_filter_pruning.sql)</li>
<li>Table Expansion (ex_table_expansion.sql)</li>
<li>Join Factorization (ex_join_factorization.sql)</li>
<li>OR Expansion (ex_or_expansion.sql)</li>
<li>Join Elimination (ex_join_elimination.sql)</li>
<li>Subquery Unnesting (ex_subquery_unnesting.sql)</li>
</ul>
</li>
<li>System and Object Statistics (DBMS_STATS)
<ul>
<li>Workload System Statistics</li>
<li>Object Statistics – Default Preferences</li>
<li>Object Statistics – Auto Sample Size</li>
<li>Object Statistics – Pending Statistics (ex_pending_object_statistics.sql)</li>
<li>Object Statistics – Incremental Statistics (ex_incremental_stats.sql)</li>
<li>Object Statistics – Extended Statistics on Expressions (ex_extended_statistics1.sql)</li>
<li>Object Statistics – Extended Statistics on Column Groups (ex_extended_statistics2.sql)</li>
<li>Object Statistics – Seeding Column Groups</li>
<li>Object Statistics – Comparing Statistics (ex_comparing_statistics.sql)</li>
<li>Object Statistics – Locks not Exported</li>
<li>JOB_QUEUE_PROCESSES</li>
</ul>
</li>
<li>Plan Stability
<ul>
<li>CURSOR_SHARING</li>
<li>SQL Plan Baselines  (ex_execution_plan_stability.sql, ex_execution_plan_stability_10g.sql, ex_execution_plan_stability_11g.sql)</li>
<li>Stored Outlines</li>
<li>Adaptive Cursor Sharing (ex_bind_peeking.sql, ex_bind_peeking_bind_aware.sql)</li>
<li>Cardinality Feedback (ex_cardinality_feedback.sql)</li>
</ul>
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/12/challenges-and-chances-of-the-11g-query-optimizer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ad: Trivadis TechEvent 2011</title>
		<link>http://www.antognini.ch/2011/12/ad-trivadis-techevent-2011/</link>
		<comments>http://www.antognini.ch/2011/12/ad-trivadis-techevent-2011/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 15:44:02 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[Trivadis]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1655</guid>
		<description><![CDATA[All Trivadis employees meet twice a year near Zurich for a unique conference called TechEvent. The TechEvents, with up to 15 parallel sessions, are among the largest IT conferences in Switzerland. During two days, employees can attend sessions about a wide range of both technical and non-technical subjects. Watch the following (German spoken) video to [...]]]></description>
			<content:encoded><![CDATA[<p>All Trivadis employees meet twice a year near Zurich for a unique conference called TechEvent.</p>
<p>The TechEvents, with up to 15 parallel sessions, are among the largest IT conferences in Switzerland. During two days, employees can attend sessions about a wide range of both technical and non-technical subjects.</p>
<p>Watch the following (German spoken) video to know more about it…</p>
<p><object style="height: 340px; width: 480px"><param name="movie" value="http://www.youtube.com/v/9aFNDPm2g5k?version=3&#038;feature=player_detailpage"><param name="allowFullScreen" value="true"><param name="allowScriptAccess" value="always"><embed src="http://www.youtube.com/v/9aFNDPm2g5k?version=3&#038;feature=player_detailpage" type="application/x-shockwave-flash" allowfullscreen="true" allowScriptAccess="always" width="480" height="270"></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/12/ad-trivadis-techevent-2011/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>SQL Trace and Oracle Portal</title>
		<link>http://www.antognini.ch/2011/11/sql-trace-and-oracle-portal/</link>
		<comments>http://www.antognini.ch/2011/11/sql-trace-and-oracle-portal/#comments</comments>
		<pubDate>Tue, 29 Nov 2011 10:32:34 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[10gR1]]></category>
		<category><![CDATA[10gR2]]></category>
		<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>
		<category><![CDATA[SQL Trace]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1637</guid>
		<description><![CDATA[Recently I was involved in a project where I had to trace the database calls of an application based on Oracle Portal 10.1.4. The basic requirements were the following: Tracing takes place in the production environment Tracing has to be enable for a single user only Instrumentation code cannot be added to the application Given [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I was involved in a project where I had to trace the database calls of an application based on Oracle Portal 10.1.4. The basic requirements were the following:</p>
<ul>
<li>Tracing takes place in the production environment</li>
<li>Tracing has to be enable for a single user only</li>
<li>Instrumentation code cannot be added to the application</li>
</ul>
<p>Given that Oracle Portal uses a pool of connections and that for each HTTP call it can use several database sessions, statically enable SQL trace for specific sessions was not an option.</p>
<p>Knowing nothing about Oracle Portal I started RTFM and, gladly, I discovered that there is a simple way to inject a piece of code before and after a requested procedure is called. This is done by setting, via the administration GUI, the parameters <a href="http://docs.oracle.com/cd/B14099_19/web.1012/b14008/confmods.htm#sthref632">PlsqlBeforeProcedure</a> and <a href="http://docs.oracle.com/cd/B14099_19/web.1012/b14008/confmods.htm#sthref625">PlsqlAfterProcedure</a>.</p>
<p>Since Oracle Portal provides a function (<a href="http://docs.oracle.com/cd/B14099_19/portal.1012/b14134/pdg_pdk_plsql.htm#sthref1442">WWCTX_API.GET_USER</a>) to get the current user, I decided to create the following procedures to set/clear the client identifier before/after every call. Note that I added the call to SUBSTR and the exception handler to make sure that the procedures do not raise exceptions (hey, it’s a production system and I do not want to impact everyone!).</p>
<pre>CREATE PROCEDURE tvd_set_client_identifier AS
BEGIN
  dbms_session.set_identifier(substr(portal.wwctx_api.get_user,1,64));
EXCEPTION
  WHEN others THEN NULL;
END;</pre>
<pre>CREATE PROCEDURE tvd_clear_client_identifier AS
BEGIN
  dbms_session.clear_identifier;
EXCEPTION
  WHEN others THEN NULL;
END;</pre>
<p>To &#8220;enable&#8221; these procedures we did the following:</p>
<ul>
<li>Set PlsqlBeforeProcedure=portal.tvd_set_client_identifier</li>
<li>Set PlsqlAfterProcedure=portal.tvd_clear_client_identifier</li>
<li>Restarted the application server</li>
</ul>
<p>With this configuration in place enabling SQL trace for a single user was easily done by calling the <a href="http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_monitor.htm#i1002256">DBMS_MONITOR.CLIENT_ID_TRACE_ENABLE</a> procedure by specifying the user to be traced as value for the CLIENT_ID parameter.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/11/sql-trace-and-oracle-portal/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Debugging PL/SQL and Java Stored Procedures with JPDA</title>
		<link>http://www.antognini.ch/2011/10/debugging-plsql-and-java-stored-procedures-with-jpda/</link>
		<comments>http://www.antognini.ch/2011/10/debugging-plsql-and-java-stored-procedures-with-jpda/#comments</comments>
		<pubDate>Tue, 18 Oct 2011 22:40:05 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1610</guid>
		<description><![CDATA[In 2003 I published a paper entitled Debugging PL/SQL and Java Stored Procedures with JPDA. Its aim was to describe how to debug PL/SQL and Java code deployed into the database with JDeveloper 9i. Two weeks ago a reader of my blog, Pradip Kumar Pathy, contacted me because he tried, without success, to do something [...]]]></description>
			<content:encoded><![CDATA[<p>In 2003 I published a paper entitled <a href="/papers/JPDA_20031115.pdf">Debugging PL/SQL and Java Stored Procedures with JPDA</a>. Its aim was to describe how to debug PL/SQL and Java code deployed into the database with JDeveloper 9i. Two weeks ago a reader of my blog, Pradip Kumar Pathy, contacted me because he tried, without success, to do something similar with JDeveloper 11g, WebLogic 11g and Oracle Database 11g. Unfortunately I was not able to help him. The reason is quite simple, since 2004 I&#8217;m an Eclipse user&#8230;</p>
<p>Few days later Pradip contacted me again to let me know that, at last, he succeeded. Here you find his notes&#8230;</p>
<ol>
<li>Grant the required privileges</li>
<p>GRANT DEBUG CONNECT SESSION to &#038;&#038;schema_name;<br />
GRANT DEBUG ANY PROCEDURE TO &#038;&#038;schema_name;</p>
<li>Create a database connection under “Application Resources” and compile the stored procedure in debug modus (<a href="/images/jpda2a.jpg" rel="lightbox">Figure 2a</a> and <a href="/images/jpda2b.jpg" rel="lightbox">Figure 2b</a>)</li>
<li>Write some Java code to let the database engine connect JDeveloper (this piece of code must be executed before calling the PL/SQL stored procedure)</li>
<pre>
private static void remotePLSQLDebug(Connection con) throws SQLException
{
  SystemProperties systemProperties = null;
  systemProperties = SystemProperties.getInstance();
  CallableStatement callState = null;
  String port = systemProperties.get("plsqldebug.port").trim();
  String storedCall = "call dbms_debug_jdwp.connect_tcp('localhost'," + port + ")";
  callState = con.prepareCall("{" + storedCall + "}");
  callState.execute();
  callState.close();
}</pre>
<li>Configure the <code>plsqldebug.port</code> parameter in the application properties</li>
<li>Edit the project properties to enable JPDA and defining the port used by the JPDA listener (<a href="/images/jpda5a.jpg" rel="lightbox">Figure 5a</a> and <a href="/images/jpda5b.jpg" rel="lightbox">Figure 5b</a>)</li>
<li>Deploy the EAR in WebLogic and start the JPDA listener configured in the previous step</li>
<li>Execute the Java code of step 3; as a result the database engine connects the JPDA listener and a connection process is created (<a href="/images/jpda7.jpg" rel="lightbox">Figure 7</a>)</li>
<li>When the PL/SQL stored procedure is executed, JDeveloper is able to debug it (open the PL/SQL stored procedure  in the “Database Navigator” for that purpose)</li>
<li>Once the debugging is over detach the connection process</li>
</ol>
<p>Thank you Pradip to share your findings!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/10/debugging-plsql-and-java-stored-procedures-with-jpda/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ad: Der Oracle DBA &#8211; Handbuch für die Administration der Oracle Database 11gR2</title>
		<link>http://www.antognini.ch/2011/10/ad-der-oracle-dba-handbuch-fur-die-administration-der-oracle-database-11gr2/</link>
		<comments>http://www.antognini.ch/2011/10/ad-der-oracle-dba-handbuch-fur-die-administration-der-oracle-database-11gr2/#comments</comments>
		<pubDate>Fri, 14 Oct 2011 09:02:49 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1591</guid>
		<description><![CDATA[The book Der Oracle DBA (Hanser, 2011), which was written in German, is at last available! I say “at last” because the authors worked on this project for not less than two years. Who are the authors? Several colleagues of mine at Trivadis (Mirko Hotzy, Konrad Häfeli, Daniel Steiger, Sven Vetter, Peter Welker), Andrea Held, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.de/gp/product/3446420819/?ie=UTF8&#038;site-redirect=de&#038;tag=strivforoptim-21&#038;linkCode=ur2&#038;camp=1638&#038;creative=6742"><img src="/images/DerOracleDBA.jpg" alt="Der Oracle DBA" /></a></p>
<p><img src="http://www.assoc-amazon.de/e/ir?t=strivforoptim-21&#038;l=ur2&#038;o=3" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" />The book <a href="http://www.amazon.de/gp/product/3446420819/?ie=UTF8&#038;site-redirect=de&#038;tag=strivforoptim-21&#038;linkCode=ur2&#038;camp=1638&#038;creative=6742">Der Oracle DBA</a><img src="http://www.assoc-amazon.de/e/ir?t=strivforoptim-21&#038;l=ur2&#038;o=3" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /> (Hanser, 2011), which was written in German, is at last available!</p>
<p>I say “at last” because the authors worked on this project for not less than two years.</p>
<p>Who are the authors? Several colleagues of mine at Trivadis (Mirko Hotzy, Konrad Häfeli, <a href="http://blog.trivadis.com/b/danielsteiger/default.aspx">Daniel Steiger</a>, <a href="http://sven.svenvetter.com/">Sven Vetter</a>, <a href="http://blog.trivadis.com/b/peterwelker/default.aspx">Peter Welker</a>), <a href="http://www.held-informatik.de/">Andrea Held</a>, Lutz Fröhlich, <a href="http://www.adar-consult.de/">Marek Adar</a> and myself.</p>
<p>For my part, I wrote two chapters: <em>Speicherplatzverwaltung</em> and <em>Optimierung</em>. The first one, Speicherplatzverwaltung, is available <a href="http://files.hanser.de/hanser/docs/20110927_211927164356-71_978-3-446-42081-6_Leseprobe.pdf">here</a>. Also available online are the <a href="http://files.hanser.de/hanser/docs/20110927_211927164312-75_978-3-446-42081-6_Inhaltsverzeichnis.pdf">table of content</a>, the <a href="http://files.hanser.de/hanser/docs/20110927_21192716434-40_978-3-446-42081-6_Vorwort.pdf">preface</a> and the <a href="http://files.hanser.de/hanser/docs/20110927_21192716448-100_978-3-446-42081-6_Register.pdf">index</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/10/ad-der-oracle-dba-handbuch-fur-die-administration-der-oracle-database-11gr2/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Impact of STATISTICS_LEVEL on Cardinality Feedback and Adaptive Cursor Sharing</title>
		<link>http://www.antognini.ch/2011/09/impact-of-statistics_level-on-cardinality-feedback-and-adaptive-cursor-sharing/</link>
		<comments>http://www.antognini.ch/2011/09/impact-of-statistics_level-on-cardinality-feedback-and-adaptive-cursor-sharing/#comments</comments>
		<pubDate>Mon, 19 Sep 2011 17:20:09 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR1]]></category>
		<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Query Optimizer]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1572</guid>
		<description><![CDATA[The STATISTICS_LEVEL parameter controls a bunch of features. In addition to the documentation, also the V$STATISTICS_LEVEL view provides a list of the ones it controls. SQL> SELECT statistics_name, description, activation_level 2 FROM v$statistics_level 3 ORDER BY 3 DESC, 1; STATISTICS_NAME DESCRIPTION ACTIVATION_LEVEL -------------------------------------- ------------------------------------------------------------ ---------------- Active Session History Monitors active session activity using MMNL TYPICAL [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17110/initparams249.htm#CHDDAHJD">STATISTICS_LEVEL</a> parameter controls a bunch of features. In addition to the <a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17110/initparams249.htm#CHDDAHJD">documentation</a>, also the <a href="http://download.oracle.com/docs/cd/E11882_01/server.112/e17110/dynviews_3075.htm#I1030264">V$STATISTICS_LEVEL</a> view provides a list of the ones it controls.</p>
<pre>SQL> SELECT statistics_name, description, activation_level
  2  FROM v$statistics_level
  3  ORDER BY 3 DESC, 1;

STATISTICS_NAME                        DESCRIPTION                                                  ACTIVATION_LEVEL
-------------------------------------- ------------------------------------------------------------ ----------------
Active Session History                 Monitors active session activity using MMNL                  TYPICAL
Adaptive Thresholds Enabled            Controls if Adaptive Thresholds should be enabled            TYPICAL
Automated Maintenance Tasks            Controls if Automated Maintenance should be enabled          TYPICAL
Bind Data Capture                      Enables capture of bind values used by SQL statements        TYPICAL
Buffer Cache Advice                    Predicts the impact of different cache sizes on number of    TYPICAL
                                       physical reads
Global Cache Statistics                RAC Buffer Cache statistics                                  TYPICAL
Longops Statistics                     Enables Longops Statistics                                   TYPICAL
MTTR Advice                            Predicts the impact of different MTTR settings on number of  TYPICAL
                                       physical I/Os
Modification Monitoring                Enables modification monitoring                              TYPICAL
PGA Advice                             Predicts the impact of different values of pga_aggregate_tar TYPICAL
                                       get on the performance of memory intensive SQL operators
Plan Execution Sampling                Enables plan lines sampling                                  TYPICAL
SQL Monitoring                         Controls if SQL Monitoring should be enabled                 TYPICAL
Segment Level Statistics               Enables gathering of segment access statistics               TYPICAL
Shared Pool Advice                     Predicts the impact of different values of shared_pool_size  TYPICAL
                                       on elapsed parse time saved
Streams Pool Advice                    Predicts impact on Streams perfomance of different  Streams  TYPICAL
                                       pool sizes
Threshold-based Alerts                 Controls if Threshold-based Alerts should be enabled         TYPICAL
Time Model Events                      Enables Statics collection for time events                   TYPICAL
Timed Statistics                       Enables gathering of timed statistics                        TYPICAL
Ultrafast Latch Statistics             Maintains statistics for ultrafast latches in the fast path  TYPICAL
Undo Advisor, Alerts and Fast Ramp up  Transaction layer manageability features                     TYPICAL
V$IOSTAT_* statistics                  Controls if I/O stats in v$iostat_ should be enabled         TYPICAL
Plan Execution Statistics              Enables collection of plan execution statistics              ALL
Timed OS Statistics                    Enables gathering of timed operating system statistics       ALL
</pre>
<p>Something that I learned only recently is that STATISTICS_LEVEL also controls <em>cardinality feedback</em> and <em>adaptive cursor sharing</em>. This fact, according to me, is neither (clearly) documented nor pointed out by the information provided by V$STATISTICS_LEVEL. In any case, when STATISTICS_LEVEL is set to BASIC at the <em>system level</em> both features are disabled. Interestingly, an ALTER SESSION SET STATISTICS_LEVEL = TYPICAL it is not enough to enable them… For adaptive cursor sharing it is possible to use the BIND_AWARE hint, though.</p>
<p>Note that I never advise to set STATISTICS_LEVEL at the system level to a value that is different from the default (TYPICAL). Probably for this reason I didn’t notice its impact for such a long time…</p>
<p>In any case I find it a bit disappointing that this information is not clearly stated somewhere. Or I’m the only one that was not aware?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.antognini.ch/2011/09/impact-of-statistics_level-on-cardinality-feedback-and-adaptive-cursor-sharing/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

