<?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 Performance &#187; Bug</title>
	<atom:link href="http://antognini.ch/category/oracledatabase/bug/feed/" rel="self" type="application/rss+xml" />
	<link>http://antognini.ch</link>
	<description></description>
	<lastBuildDate>Sat, 17 Dec 2011 23:42:45 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Challenges and Chances of the 11g Query Optimizer</title>
		<link>http://antognini.ch/2011/12/challenges-and-chances-of-the-11g-query-optimizer/</link>
		<comments>http://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 exception [...]]]></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://antognini.ch/2011/12/challenges-and-chances-of-the-11g-query-optimizer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Workload System Statistics Bug in 11.2</title>
		<link>http://antognini.ch/2010/11/workload-system-statistics-in-11g/</link>
		<comments>http://antognini.ch/2010/11/workload-system-statistics-in-11g/#comments</comments>
		<pubDate>Tue, 23 Nov 2010 10:07:35 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[System Statistics]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1443</guid>
		<description><![CDATA[Since the introduction of 11.2 I receive on a regular basis questions related to “strange” workload system statistics. The last email on that topic was sent to me yesterday. So, instead to send, again, a private reply, I decided to write this short post.
What’s wrong with 11.2 and workload system statistics?
Let’s have a look to [...]]]></description>
			<content:encoded><![CDATA[<p>Since the introduction of 11.2 I receive on a regular basis questions related to “strange” workload system statistics. The last email on that topic was sent to me yesterday. So, instead to send, again, a private reply, I decided to write this short post.</p>
<p>What’s wrong with 11.2 and workload system statistics?</p>
<p>Let’s have a look to the output of the following query:</p>
<p><pre>SQL&gt; SELECT pname, pval1
  2  FROM sys.aux_stats$
  3  WHERE sname = &#039;SYSSTATS_MAIN&#039;;

PNAME                  PVAL1
--------------- ------------
CPUSPEEDNW            1596.0
IOSEEKTIM                4.0
IOTFRSPEED            4096.0
SREADTIM             10900.3
MREADTIM              4525.8
CPUSPEED              1603.0
MBRC                     7.0
MAXTHR            17391616.0
SLAVETHR            413696.0</pre></p>
<p>As you can see the SREADTIM and MREADTIM times are very high. In this case about three orders of magnitude of what you would expect from a regular system. </p>
<p>I’m not aware of the exact cause of this problem, but to me it seems that the statistics externalized in x$kcfio are broken. Anyway, in MOS there are several bugs related to it  (<a href="https://supporthtml.oracle.com/ep/faces/secure/km/BugDisplay.jspx?id=9842771&#038;bugProductSource=Oracle&#038;h=Y">9842771</a> and <a href="https://supporthtml.oracle.com/ep/faces/secure/km/BugDisplay.jspx?id=9701256&#038;bugProductSource=Oracle&#038;h=Y">9701256</a>). Hence, it’s not a feature (e.g. a change in the unit of measure), it’s a bug. On my Linux test system I’m able to reproduce it on both 11.2.0.1 and 11.2.0.2. According to the bugs mentioned before, the problem is not limited to Linux.</p>
<p>Since with the DBMS_STATS package we are not able to gather correct statistics, the only advice I can give on that topic is that you have to manually set them to sensible values. </p>
<p><strong>Update 2011-03-23</strong></p>
<p>To fix the problem you can install the patch 9842771. It is available for 11.2.0.1 and 11.2.0.2. By the way, since the patch only provides a new version of the dbms_stats_internal package, the statistics externalized in x$kcfio are not broken&#8230; they just have another unit of measure.</p>
<p><strong>Update 2011-10-10</strong></p>
<p>The fix for this problem is included in the 11.2.0.3 patch set.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2010/11/workload-system-statistics-in-11g/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>DBMS_AUTO_SQLTUNE: ORA-01748 and Documentation Bugs</title>
		<link>http://antognini.ch/2010/10/dbms_auto_sqltune-ora-01748-and-documentation-bugs/</link>
		<comments>http://antognini.ch/2010/10/dbms_auto_sqltune-ora-01748-and-documentation-bugs/#comments</comments>
		<pubDate>Wed, 06 Oct 2010 15:04:00 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Query Optimizer]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1328</guid>
		<description><![CDATA[As of 11.2.0.2 a new package, DBMS_AUTO_SQLTUNE, is available for accessing and configuring Automatic SQL Tuning. The package provides three features:

Execution of the Automatic SQL Tuning task (EXECUTE_AUTO_TUNING_TASK)
Generation of a report showing the output generated by the Automatic SQL Tuning tasks (REPORT_AUTO_TUNING_TASK)
Configuration of the Automatic SQL Tuning parameters (SET_AUTO_TUNING_TASK_PARAMETER)

In this post I would like to [...]]]></description>
			<content:encoded><![CDATA[<p>As of 11.2.0.2 a new package, DBMS_AUTO_SQLTUNE, is available for accessing and configuring Automatic SQL Tuning. The package provides three features:</p>
<ul>
<li>Execution of the Automatic SQL Tuning task (EXECUTE_AUTO_TUNING_TASK)</li>
<li>Generation of a report showing the output generated by the Automatic SQL Tuning tasks (REPORT_AUTO_TUNING_TASK)</li>
<li>Configuration of the Automatic SQL Tuning parameters (SET_AUTO_TUNING_TASK_PARAMETER)</li>
</ul>
<p>In this post I would like to focus on the second functionality. With it you can for example execute the following commands in SQL*Plus to get a report for the most recent task:</p>
<p><pre>SET LONG 1000000 PAGESIZE 0 LINESIZE 200
COLUMN report_auto_tuning_task FORMAT A200
SELECT dbms_auto_sqltune.report_auto_tuning_task FROM dual;</pre></p>
<p>The REPORT_AUTO_TUNING_TASK function is not limited to being used without parameters. In fact, its signature is the following:</p>
<p><pre>FUNCTION REPORT_AUTO_TUNING_TASK RETURNS CLOB
 Argument Name                  Type                    In/Out Default?
 ------------------------------ ----------------------- ------ --------
 BEGIN_EXEC                     VARCHAR2                IN     DEFAULT
 END_EXEC                       VARCHAR2                IN     DEFAULT
 TYPE                           VARCHAR2                IN     DEFAULT
 LEVEL                          VARCHAR2                IN     DEFAULT
 SECTION                        VARCHAR2                IN     DEFAULT
 OBJECT_ID                      NUMBER                  IN     DEFAULT
 RESULT_LIMIT                   NUMBER                  IN     DEFAULT</pre></p>
<p>The purpose of the parameters is the following:</p>
<ul>
<li>BEGIN_EXEC/END_EXEC specifies which tasks have to be reported. With the default value, NULL, the most recent task is shown.</li>
<li>TYPE specifies the type of the report. Presently only TEXT is supported.</li>
<li>LEVEL specifies the level of detail shown in the report. This is somewhat similar to the FORMAT parameter of DBMS_XPLAN. The supported values are BASIC, TYPICAL (default) and ALL.</li>
<li>SECTION specifies which sections are shown in the report. The supported values are SUMMARY, FINDINGS, PLANS, INFORMATION, ERRORS and ALL (default). Possibly there is a bug with the value ERRORS. In fact, during my tests, it always returned the same report as the value INFORMATION!?!?</li>
<li>OBJECT_ID restricts the report to a single SQL statement. You can get the ID either from the report or by querying DBA_ADVISOR_OBJECTS.OBJECT_ID.</li>
<li>RESULT_LIMIT specifies the maximum number of SQL statements shown in the report.</li>
</ul>
<p>The essential thing I would like to point out is that two parameters have as name a reserved word.</p>
<p><pre>SQL&gt; SELECT keyword
  2  FROM v$reserved_words
  3  WHERE keyword IN (&#039;BEGIN_EXEC&#039;,&#039;END_EXEC&#039;,&#039;TYPE&#039;,&#039;LEVEL&#039;,&#039;SECTION&#039;,&#039;OBJECT_ID&#039;,&#039;RESULT_LIMIT&#039;);

KEYWORD
------------------------------
LEVEL
TYPE</pre></p>
<p>As a result expect to get an error like the following one if you want to use named notation:</p>
<p><pre>SELECT dbms_auto_sqltune.report_auto_tuning_task(level =&gt; &#039;basic&#039;) FROM dual
                                                       *
ERROR at line 1:
ORA-01748: only simple column names allowed here</pre></p>
<p>These are the kind of things I cannot understand! It&#8217;s so easy to choose a name that doesn&#8217;t lead to such problems. For one time I hope that Oracle will break backward compatibility and change the name of these parameters.</p>
<p>Another thing I wanted to point out is that the values supported by the SECTION parameter are the ones I reported above, and not the ones documented <a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e16760/d_autosta.htm#CIAEHBGA">here</a>. In fact, there are two typos in the documentation. This is probably because the same typos can also be seen in $ORACLE_HOME/rdbms/admin/dbmssqlt.sql. In other words, it seems that the guy who wrote the documentation did a simple copy/paste of the content of the SQL file.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2010/10/dbms_auto_sqltune-ora-01748-and-documentation-bugs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Exadata Storage Server and the Query Optimizer – Part 4</title>
		<link>http://antognini.ch/2010/08/exadata-storage-server-and-the-query-optimizer-%e2%80%93-part-4/</link>
		<comments>http://antognini.ch/2010/08/exadata-storage-server-and-the-query-optimizer-%e2%80%93-part-4/#comments</comments>
		<pubDate>Mon, 09 Aug 2010 15:37:40 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Exadata]]></category>
		<category><![CDATA[Query Optimizer]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1227</guid>
		<description><![CDATA[When I started writing the series of posts about Exadata Storage Server and the query optimizer, I didn’t expect to write more than three posts (part 1, part 2, part 3). Of course, things change. Hence, here is part 4 to cover a couple of things that I learned in the next couple of months.
In [...]]]></description>
			<content:encoded><![CDATA[<p>When I started writing the series of posts about Exadata Storage Server and the query optimizer, I didn’t expect to write more than three posts (<a href="/2010/04/exadata-storage-server-and-the-query-optimizer-part-1/">part 1</a>, <a href="/2010/05/exadata-storage-server-and-the-query-optimizer-%e2%80%93-part-2/">part 2</a>, <a href="/2010/05/exadata-storage-server-and-the-query-optimizer-part-3/">part 3</a>). Of course, things change. Hence, here is part 4 to cover a couple of things that I learned in the next couple of months.</p>
<p>In <a href="/2010/05/exadata-storage-server-and-the-query-optimizer-%e2%80%93-part-2/">part 2</a> I pointed out that Oracle Database is not able to offload the processing of all datetime functions. This fact, to my surprise, was also referenced by <a href="http://www.netezza.com/">Netezza</a> in a recent paper entitled <a href="http://www.netezza.com/exadata-twinfin-compared/index.aspx">Oracle Exadata and Netezza TwinFin Compared</a>. The essential thing to understand is that this limitation is due to bug 9682721. The fix is expected to be part of 11.2.0.2. According to my test cases (that <a href="http://structureddata.org/">Greg Rahn</a> was so kind to execute against an early release of 11.2.0.2), offloading works correctly for all datetime functions but for the following three predicates.</p>
<ul>
<li>months_between(d,sysdate) = 0</li>
<li>months_between(d,current_date) = 0</li>
<li>months_between(d,to_date(&#8216;01-01-2010&#8242;,&#8217;DD-MM-YYYY&#8217;)) = 0</li>
</ul>
<p>Note that the MONTHS_BETWEEN function can basically be offloaded. The problem in these cases is that the offloading does not work when, for example, SYSDATE is used as parameter.</p>
<p>To have a full list of the functions supporting offloading, the “official reference” is available through the V$SQLFN_METADATA view. Here is a simple query to summarize the current situation.</p>
<p><pre>SQL&gt; SELECT offloadable, count(DISTINCT name)
  2  FROM v$sqlfn_metadata
  3  GROUP BY offloadable;

OFF COUNT(DISTINCTNAME)
--- -------------------
NO                  511
YES                 319</pre></p>
<p>Another thing I would like to point out about offloading is that the feature can be controlled through the CELL_OFFLOAD_PROCESSING initialization parameter. By default it is set to TRUE and, therefore, offloading is used whenever possible. It goes without saying that offloading is disabled when it is set to FALSE. Note that it can not only be set at the instance and session level, but also at the statement level. The following example illustrate this (notice that only the first query uses offloading).</p>
<p><pre>SQL&gt; ALTER SESSION SET cell_offload_plan_display = always;

SQL&gt; ALTER SESSION SET cell_offload_processing = true;

SQL&gt; EXPLAIN PLAN FOR SELECT * FROM t WHERE id = 101;

SQL&gt; SELECT * FROM table(dbms_xplan.display(format=&gt;&#039;basic +predicate&#039;));

PLAN_TABLE_OUTPUT
---------------------------------------------------
Plan hash value: 3557914527

-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|   1 |  PARTITION RANGE ALL       |      |
|*  2 |   TABLE ACCESS STORAGE FULL| T    |
-------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - storage(&quot;ID&quot;=101)
       filter(&quot;ID&quot;=101)

SQL&gt; EXPLAIN PLAN FOR SELECT /*+ opt_param(&#039;cell_offload_processing&#039; &#039;false&#039;) */  * FROM t WHERE id = 101;

SQL&gt; SELECT * FROM table(dbms_xplan.display(format=&gt;&#039;basic +predicate&#039;));

PLAN_TABLE_OUTPUT
---------------------------------------------------
Plan hash value: 3557914527

-------------------------------------------
| Id  | Operation                  | Name |
-------------------------------------------
|   0 | SELECT STATEMENT           |      |
|   1 |  PARTITION RANGE ALL       |      |
|*  2 |   TABLE ACCESS STORAGE FULL| T    |
-------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - filter(&quot;ID&quot;=101)</pre></p>
<p>Another initialization parameter that controls offloading is CELL_OFFLOAD_DECRYPTION. This parameter is relevant for encrypted tablespaces only. With it you can specify whether the keys necessary to decrypt the data can be shipped to the cells. By default it is set to TRUE and, therefore, the keys are shipped. For security reasons you might want to set it to FALSE and disable offloading for encrypted tablespaces. Note that this parameter can only be changed at the instance level.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2010/08/exadata-storage-server-and-the-query-optimizer-%e2%80%93-part-4/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Optimizer Mode Mismatch Does Not Prevent Sharing of Child Cursor!?!?</title>
		<link>http://antognini.ch/2010/06/optimizer-mode-mismatch-does-not-prevent-sharing-of-child-cursor/</link>
		<comments>http://antognini.ch/2010/06/optimizer-mode-mismatch-does-not-prevent-sharing-of-child-cursor/#comments</comments>
		<pubDate>Thu, 03 Jun 2010 17:40:03 +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[9iR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Query Optimizer]]></category>
		<category><![CDATA[SQL Trace]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1113</guid>
		<description><![CDATA[The aim of this post is to describe a strange (buggy) situation that I observed recently. But before doing that, I shortly summarize what a parent cursor and a child cursor are as well as when they can be shared. By the way, I borrowed this description from the pages 20/21 of my book. Hence, [...]]]></description>
			<content:encoded><![CDATA[<p>The aim of this post is to describe a strange (buggy) situation that I observed recently. But before doing that, I shortly summarize what a parent cursor and a child cursor are as well as when they can be shared. By the way, I borrowed this description from the pages 20/21 of my <a href="/top">book</a>. Hence, if you are interested in more information about this topic refer to it…</p>
<p>The result of a parse operation is a parent cursor and a child cursor stored in the library cache.</p>
<p>The key information related to a parent cursor is the text of the SQL statement. Therefore, several SQL statements share the same parent cursor if their text is exactly the same (note that there is at least an exception to this, specifically when cursor sharing is used). In the following example, four SQL statements are executed. Two have the same text. Two others differ only because of lowercase and uppercase letters or blanks. Through the V$SQLAREA view, it is possible to confirm that three distinct parent cursors were created.</p>
<p><pre>SQL&gt; ALTER SYSTEM FLUSH SHARED_POOL;

SQL&gt; SELECT * FROM t WHERE n = 1234;

SQL&gt; select * from t where n = 1234;

SQL&gt; SELECT * FROM t WHERE n=1234;

SQL&gt; SELECT * FROM t WHERE n = 1234;

SQL&gt; SELECT sql_id, sql_text, executions
  2  FROM v$sqlarea
  3  WHERE sql_text LIKE &#039;%1234&#039;;

SQL_ID        SQL_TEXT                          EXECUTIONS
------------- --------------------------------- ----------
2254m1487jg50 select * from t where n = 1234             1
g9y3jtp6ru4cb SELECT * FROM t WHERE n = 1234             2
7n8p5s2udfdsn SELECT * FROM t WHERE n=1234               1</pre></p>
<p>The key information related to a child cursor is the execution plan and the execution environment related to it. The execution environment is important because if it changes, the execution plan might change as well. As a result, several SQL statements are able to share the same child cursor only if they share the same parent cursor and their execution environments are compatible. To illustrate, the same SQL statement is executed with two different values of the initialization OPTIMIZER_MODE parameter. The result is that a single parent cursor and two child cursors are created.</p>
<p><pre>SQL&gt; ALTER SESSION SET optimizer_mode = all_rows;

SQL&gt; SELECT count(*) FROM t;

COUNT(*)
----------
      1000

SQL&gt; ALTER SESSION SET optimizer_mode = first_rows_10;

SQL&gt; SELECT count(*) FROM t;

COUNT(*)
----------
      1000

SQL&gt; SELECT sql_id, child_number, sql_text, optimizer_mode, plan_hash_value
  2  FROM v$sql
  3  WHERE sql_id = (SELECT prev_sql_id
  4  FROM v$session
  5  WHERE sid = sys_context(&#039;userenv&#039;,&#039;sid&#039;));

SQL_ID        CHILD_NUMBER SQL_TEXT               OPTIMIZER_MODE PLAN_HASH_VALUE
------------- ------------ ---------------------- -------------- ---------------
5tjqf7sx5dzmj            0 SELECT count(*) FROM t ALL_ROWS            2966233522
5tjqf7sx5dzmj            1 SELECT count(*) FROM t FIRST_ROWS          2966233522</pre></p>
<p>To know which mismatch led to several child cursors, you can query the V$SQL_SHARED_CURSOR view.</p>
<p><pre>SQL&gt; SELECT child_number, optimizer_mode_mismatch
  2  FROM v$sql_shared_cursor
  3  WHERE sql_id = &#039;5tjqf7sx5dzmj&#039;;

CHILD_NUMBER OPTIMIZER_MODE_MISMATCH
------------ -----------------------
           0 N
           1 Y</pre></p>
<p>So far, so good… Now, let’s see what’s strange…</p>
<p>The interesting thing to point out about the previous example is that while I set FIRST_ROWS_10 as optimizer mode, the V$SQL view displayed the value FIRST_ROWS. Mhmm… That’s strange… They are two different optimizer modes. They cannot be considered equivalent. What are the implications? It is just the view that provides the wrong information or the database engine is able to share the same child cursor even with two different values of the OPTIMIZER_MODE parameter? Let’s try it with FIRST_ROWS (i.e. without “_10”)…</p>
<p><pre> SQL&gt; ALTER SESSION SET optimizer_mode = first_rows;

SQL&gt; SELECT sql_id, child_number, sql_text, optimizer_mode, executions
  2  FROM v$sql
  3  WHERE sql_id = (SELECT prev_sql_id
  4                  FROM v$session
  5                  WHERE sid = sys_context(&#039;userenv&#039;,&#039;sid&#039;));

SQL_ID        CHILD_NUMBER SQL_TEXT                          OPTIMIZER_MODE EXECUTIONS
------------- ------------ --------------------------------- -------------- ----------
5tjqf7sx5dzmj            0 SELECT count(*) FROM t            ALL_ROWS                1
5tjqf7sx5dzmj            1 SELECT count(*) FROM t            FIRST_ROWS              2</pre></p>
<p>Oh, damn! Even though the OPTIMIZER MODE is set to a different value the same child cursor is used. Since in this particular situation the execution plans associated to both child cursors are the same (their hash value are equal), it’s not a real problem. But, in practice, it might be possible that two different optimizer modes lead to different execution plans. The following example illustrates this.</p>
<ul>
<li>Build a table for the test:</li>
</ul>
<p><pre>SQL&gt; CREATE TABLE t AS
  2  SELECT rownum AS id, rpad(&#039;*&#039;,500,&#039;*&#039;) AS pad
  3  FROM dual
  4  CONNECT BY level &lt;= 1000;

SQL&gt; CREATE UNIQUE INDEX i ON t (id);

SQL&gt; execute dbms_stats.gather_table_stats(user, &#039;T&#039;)</pre></p>
<ul>
<li>Show that different values of the OPTIMIZER_MODE parameter lead to different execution plans:</li>
</ul>
<p><pre>SQL&gt; ALTER SESSION SET optimizer_mode = FIRST_ROWS_1;

SQL&gt; EXPLAIN PLAN FOR SELECT * FROM t WHERE id &lt;= 500;

SQL&gt; SELECT * FROM table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
Plan hash value: 242607798

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

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

   2 - access(&quot;ID&quot;&lt;=500)

SQL&gt; ALTER SESSION SET optimizer_mode = FIRST_ROWS_1000;

SQL&gt; EXPLAIN PLAN FOR SELECT * FROM t WHERE id &lt;= 500;

SQL&gt; SELECT * FROM table(dbms_xplan.display);

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

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |   500 |   246K|    10   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| T    |   500 |   246K|    10   (0)| 00:00:01 |
--------------------------------------------------------------------------

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

   1 - filter(&quot;ID&quot;&lt;=500)</pre></p>
<ul>
<li>Execute the test query with both values of the OPTIMIZER_MODE parameter:</li>
</ul>
<p><pre>SQL&gt; ALTER SYSTEM FLUSH SHARED_POOL;

SQL&gt; ALTER SESSION SET optimizer_mode = FIRST_ROWS_1;

SQL&gt; SELECT * FROM t WHERE id &lt;= 500;

        ID PAD
---------- ----------
         1 **********
         2 **********
…
       499 **********
       500 **********

SQL&gt; ALTER SESSION SET optimizer_mode = FIRST_ROWS_1000;

SQL&gt; SELECT * FROM t WHERE id &lt;= 500;

        ID PAD
---------- ----------
         1 **********
         2 **********
…
       499 **********
       500 **********</pre></p>
<ul>
<li>Show that a single execution plan was used for both executions:</li>
</ul>
<p><pre>SQL&gt; SELECT * FROM table(dbms_xplan.display_cursor(NULL,NULL));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------
SQL_ID  2vw03p929jzgz, child number 0
-------------------------------------
SELECT * FROM t WHERE id &lt;= 500

Plan hash value: 242607798

------------------------------------------------------------------------------------
| Id  | Operation                   | Name | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |      |       |       |     3 (100)|          |
|   1 |  TABLE ACCESS BY INDEX ROWID| T    |     3 |  1515 |     3   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | I    |       |       |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------

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

   2 - access(&quot;ID&quot;&lt;=500)

SQL&gt; SELECT sql_id, child_number, executions, optimizer_mode
  2  FROM v$sql
  3  WHERE sql_id = &#039;2vw03p929jzgz&#039;;

SQL_ID        CHILD_NUMBER EXECUTIONS OPTIMIZER_MODE
------------- ------------ ---------- --------------
2vw03p929jzgz            0          2 FIRST_ROWS</pre></p>
<p>Even though it is not very likely that this bug (yes, in my opinion something like this cannot be considered a restriction of the implementation…) has an impact on a production system, I really don’t understand why the developers didn’t implement it correctly. It should not be that difficult to manage a byte containing the information about the used optimizer mode! Note that this is not the only case where something like that happens with the first rows optimizer mode. For example, also in a trace file generated through SQL trace no difference is made between the old and the new first row optimizer. So, it seams that they really got it wrong.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2010/06/optimizer-mode-mismatch-does-not-prevent-sharing-of-child-cursor/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>How Good Are the Values Returned by DBMS_COMPRESSION.GET_COMPRESSION_RATIO?</title>
		<link>http://antognini.ch/2010/05/how-good-are-the-values-returned-by-dbms_compression-get_compression_ratio/</link>
		<comments>http://antognini.ch/2010/05/how-good-are-the-values-returned-by-dbms_compression-get_compression_ratio/#comments</comments>
		<pubDate>Thu, 20 May 2010 00:00:17 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Exadata]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=1078</guid>
		<description><![CDATA[According to the documentation the GET_COMPRESSION_RATIO procedure of the DBMS_COMPRESSION package can be used to assess the impact of different compression options for a given table. In other words, it allows us to find out the expected compression ratio for a given set of data without having to really create a compressed table. The question [...]]]></description>
			<content:encoded><![CDATA[<p>According to the <a href="http://download.oracle.com/docs/cd/E11882_01/appdev.112/e10577/d_compress.htm">documentation</a> the GET_COMPRESSION_RATIO procedure of the DBMS_COMPRESSION package can be used to assess the impact of different compression options for a given table. In other words, it allows us to find out the expected compression ratio for a given set of data without having to really create a compressed table. The question is: how good are the values it returns?</p>
<p>Before answering this question it is essential to point out two things. First, this package is available as of 11.2 only. Second, it can be used to find out (and compare) the expected compression ratio of OLTP compression as well as Exadata Hybrid Columnar Compression (EHCC). Note that for getting values about EHCC it is not required to actually have access to an Exadata Storage Server. How is that possible?</p>
<p>To answer this second question, let’s describe how such an analysis is performed…</p>
<p>The following PL/SQL block shows how to start an analysis for all uncompressed tables of the current user.</p>
<p><pre>DECLARE
  l_blkcnt_cmp       BINARY_INTEGER;
  l_blkcnt_uncmp     BINARY_INTEGER;
  l_row_cmp          BINARY_INTEGER;
  l_row_uncmp        BINARY_INTEGER;
  l_cmp_ratio        NUMBER;
  l_comptype_str     VARCHAR2(100);
BEGIN
  FOR i IN (SELECT table_name
            FROM user_tables
            WHERE compression = &#039;DISABLED&#039;
            ORDER BY table_name)
  LOOP
    FOR j IN 1..5
    LOOP
      dbms_compression.get_compression_ratio(
        -- input parameters
        scratchtbsname   =&gt; &#039;SCRATCH&#039;,       -- scratch tablespace
        ownname          =&gt; user,            -- owner of the table
        tabname          =&gt; i.table_name,    -- table name
        partname         =&gt; NULL,            -- partition name
        comptype         =&gt; power(2,j),      -- compression algorithm
        -- output parameters
        blkcnt_cmp       =&gt; l_blkcnt_cmp,    -- number of compressed blocks
        blkcnt_uncmp     =&gt; l_blkcnt_uncmp,  -- number of uncompressed blocks
        row_cmp          =&gt; l_row_cmp,       -- number of rows in a compressed block
        row_uncmp        =&gt; l_row_uncmp,     -- number of rows in an uncompressed block
        cmp_ratio        =&gt; l_cmp_ratio,     -- compression ratio
        comptype_str     =&gt; l_comptype_str   -- compression type
      );
      dbms_output.put_line(i.table_name||&#039; - &#039;||&#039;type: &#039;||l_comptype_str||&#039; ratio: &#039;||to_char(l_cmp_ratio,&#039;99.999&#039;));
    END LOOP;
  END LOOP;
END;</pre></p>
<p>As you can see the idea is that we provide to the package a table and, based on its data, the package estimates the compression ratio that can be achieved with the specified algorithm. Notice that as input parameter a scratch tablespace is also specified. This is necessary because the package, to estimate the output parameters, actually creates a compressed table. If you trace an execution you would see two CREATE TABLE statements.</p>
<ul>
<li>The first one creates a scratch table based on a sample of the content of the input table (the sampling percentage is chosen based on the size of the table; simply put the sampling percentage is inversely proportional to the table size):</li>
</ul>
<p><pre>CREATE TABLE dbms_tabcomp_temp_uncmp
TABLESPACE &lt;tablespace name&gt;
AS
SELECT * FROM &lt;table name&gt; SAMPLE BLOCK( &lt;sampling percentage&gt; )</pre></p>
<ul>
<li>The second one creates another scratch table where the data is compressed according to the specified compression algorithm (in this case COMPRESS FOR QUERY HIGH):</li>
</ul>
<p><pre>CREATE TABLE dbms_tabcomp_temp_uncmp
ORGANIZATION HEAP
TABLESPACE &lt;tablespace name&gt;
COMPRESS FOR QUERY HIGH
AS
SELECT * FROM dbms_tabcomp_temp_uncmp</pre></p>
<p>In other words the estimations are based on data that is actually compressed. Not on some heuristics&#8230;</p>
<p>The essential thing to note is that the second CREATE TABLE statement cannot be directly executed without an Exadata Storage Server. In fact, if you try to run it, the database engine raises an ORA-64307 (hybrid columnar compression is only supported in tablespaces residing on Exadata storage). Based on that observation it is sensible to say that in the current implementation there is a software lock that prevents us from using EHCC without an Exadata Storage Server. But, as just described, that lock can be overridden by the DBMS_COMPRESSION package.</p>
<p>Now, back to the initial question: how good are the values it returns?</p>
<p>To answer this question I installed a <a href="http://tpc.org/tpch/default.asp">TPC-H</a> schema (scale factor 10) and compared the estimations of the package with the actual values. For that purpose I created one table with each type of compression.</p>
<ul>
<li>The compression ratios based on the BLOCKS column of the USER_TABLES view are the following:</li>
</ul>
<p><pre>SQL&gt; SELECT comp.table_name, round(uncomp.blocks/comp.blocks,3) AS ratio
  2  FROM user_tables comp, user_tables uncomp
  3  WHERE comp.compression = &#039;ENABLED&#039;
  4  AND uncomp.compression = &#039;DISABLED&#039;
  5  AND comp.table_name LIKE uncomp.table_name||&#039;/_%&#039; ESCAPE &#039;/&#039;
  6  ORDER BY uncomp.table_name, nullif(comp.compress_for,&#039;OLTP&#039;) DESC;

TABLE_NAME                          RATIO
------------------------------ ----------
CUSTOMER_OLTP                       1.041
CUSTOMER_QUERY_LOW                  2.220
CUSTOMER_QUERY_HIGH                 3.708
CUSTOMER_ARCHIVE_LOW                3.837
CUSTOMER_ARCHIVE_HIGH               4.432
LINEITEM_OLTP                       1.487
LINEITEM_QUERY_LOW                  3.034
LINEITEM_QUERY_HIGH                 4.912
LINEITEM_ARCHIVE_LOW                5.144
LINEITEM_ARCHIVE_HIGH               6.704
ORDERS_OLTP                         1.149
ORDERS_QUERY_LOW                    2.887
ORDERS_QUERY_HIGH                   5.038
ORDERS_ARCHIVE_LOW                  5.305
ORDERS_ARCHIVE_HIGH                 6.704
PART_OLTP                           1.328
PART_QUERY_LOW                      3.307
PART_QUERY_HIGH                     6.718
PART_ARCHIVE_LOW                    7.296
PART_ARCHIVE_HIGH                  11.049
PARTSUPP_OLTP                       0.991
PARTSUPP_QUERY_LOW                  2.892
PARTSUPP_QUERY_HIGH                 5.428
PARTSUPP_ARCHIVE_LOW                5.659
PARTSUPP_ARCHIVE_HIGH               8.071</pre></p>
<ul>
<li>The output of the PL/SQL block shown above is the following (be careful that the order is slightly different):</li>
</ul>
<p><pre>CUSTOMER - type: &quot;Compress For OLTP&quot; ratio:   1.041
CUSTOMER - type: &quot;Compress For Query High&quot; ratio:   3.742
CUSTOMER - type: &quot;Compress For Query Low&quot; ratio:   2.228
CUSTOMER - type: &quot;Compress For Archive High&quot; ratio:   4.460
CUSTOMER - type: &quot;Compress For Archive Low&quot; ratio:   3.894
ORDERS - type: &quot;Compress For OLTP&quot; ratio:   1.149
ORDERS - type: &quot;Compress For Query High&quot; ratio:   5.048
ORDERS - type: &quot;Compress For Query Low&quot; ratio:   2.886
ORDERS - type: &quot;Compress For Archive High&quot; ratio:   6.651
ORDERS - type: &quot;Compress For Archive Low&quot; ratio:   5.325
PART - type: &quot;Compress For OLTP&quot; ratio:   1.328
PART - type: &quot;Compress For Query High&quot; ratio:   6.778
PART - type: &quot;Compress For Query Low&quot; ratio:   3.338
PART - type: &quot;Compress For Archive High&quot; ratio:  11.126
PART - type: &quot;Compress For Archive Low&quot; ratio:   7.343
PARTSUPP - type: &quot;Compress For OLTP&quot; ratio:    .990
PARTSUPP - type: &quot;Compress For Query High&quot; ratio:   5.451
PARTSUPP - type: &quot;Compress For Query Low&quot; ratio:   2.893
PARTSUPP - type: &quot;Compress For Archive High&quot; ratio:   8.051
PARTSUPP - type: &quot;Compress For Archive Low&quot; ratio:   5.657</pre></p>
<p>By comparing the estimations with the actual values it is possible to say that the value returned by the DBMS_COMPRESSION package are very accurate. Having so accurate estimations is a good thing because you probably want to know how much space you can save before doing a major reorganization of large tables as well as before buying an Exadata Storage Server just to test how effective the compression of EHCC is.</p>
<p>You might ask why the second output does not provide information about the LINEITEM table. The problem is that the package was not able to process it. In fact, the following error was raised:</p>
<p><pre>ORA-00942: table or view does not exist
ORA-06512: at &quot;SYS.PRVT_COMPRESSION&quot;, line 459
ORA-30562: SAMPLE percentage must be in the range [0.000001,100)
ORA-06512: at &quot;SYS.DBMS_COMPRESSION&quot;, line 214
ORA-06512: at line 16</pre></p>
<p>The problem is (probably) due to a rounding performed during the selection of the sampling percentage. In fact, for the LINEITEM table (which is the bigger one), the following CREATE TABLE statement was generated (notice that the sampling percentage is set to 0):</p>
<p><pre>CREATE TABLE dbms_tabcomp_temp_uncmp
TABLESPACE scratch
AS
SELECT *
FROM lineitem SAMPLE BLOCK( 0)</pre></p>
<p>I was not able to find a bug in <a href="http://support.oracle.com/">MOS</a>, but it is definitely one. </p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2010/05/how-good-are-the-values-returned-by-dbms_compression-get_compression_ratio/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>A-Rows and DML Statements</title>
		<link>http://antognini.ch/2009/07/a-rows-and-dml-statements/</link>
		<comments>http://antognini.ch/2009/07/a-rows-and-dml-statements/#comments</comments>
		<pubDate>Fri, 31 Jul 2009 10:15:30 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[10gR1]]></category>
		<category><![CDATA[10gR2]]></category>
		<category><![CDATA[11gR1]]></category>
		<category><![CDATA[9iR2]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[TOP]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=444</guid>
		<description><![CDATA[Today&#8217;s post is dedicated to the Metalink SR identified by the number 6468252.994. I know, this number says nothing to you. For me, however, it’s a very well known number. The reason is quite simple… Even if I open this SR almost two years ago (to be precise, September 5, 2007), it was closed few [...]]]></description>
			<content:encoded><![CDATA[<p>Today&#8217;s post is dedicated to the Metalink SR identified by the number 6468252.994. I know, this number says nothing to you. For me, however, it’s a very well known number. The reason is quite simple… Even if I open this SR almost two years ago (to be precise, September 5, 2007), it was closed few days ago. By far the most long-lasting SR I even experienced.</p>
<p>Let me explain why I opened it.</p>
<p>When assessing execution plans I like to use DBMS_XPLAN or, when necessary, to directly look at views like V$SQL_PLAN_STATISTICS and V$SQL_PLAN_STATISTICS_ALL. I like them because they provide a lot of information about what’s going on. In other words, they help me avoiding guesswork as much as possible. One of the most interesting information they provide is the number of rows <em>returned</em> by a given operation. DBMS_XPLAN provides this information in the column “A-Rows”. Be careful to not confuse it with the columns “Rows” and “E-Rows”. While “A-Rows” shows the <em>actual</em> number of rows, the other two shows the <em>estimated</em> number of rows. So far, so good.</p>
<p>What I don’t like about the column “A-Rows” (or the underlying columns LAST_OUTPUT_ROWS in the V$ views), is that for the operations modifying a table 0 is shown. By the way, according to the <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/dynviews_3052.htm#REFRN30251">documentation</a> it is not a bug. In my <a href="http://antognini.ch/top/">book</a> I point out this behavior at page 233. For example, as the following SQL statements show, even if 14 rows are modified the value of “A-Rows” for the operation UPDATE (Id=1) is 0:</p>
<p><pre>SQL&gt; UPDATE /*+ gather_plan_statistics */ scott.emp SET sal = sal * 1.15;

14 rows updated.

SQL&gt; SELECT * FROM table(dbms_xplan.display_cursor(format=&gt;&#039;iostats last&#039;));

SQL_ID  4cs72g2hp6j67, child number 0
-------------------------------------
UPDATE /*+ gather_plan_statistics */ scott.emp SET sal = sal * 1.15

Plan hash value: 1494045816

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |      |      1 |        |      0 |00:00:00.01 |      25 |
|   1 |  UPDATE            | EMP  |      1 |        |      0 |00:00:00.01 |      25 |
|   2 |   TABLE ACCESS FULL| EMP  |      1 |     14 |     14 |00:00:00.01 |       7 |
-------------------------------------------------------------------------------------</pre></p>
<p>Back to the SR. What I tried to do with the SR is to convince Oracle that it would be much better to have the information about the number of modified rows. Unfortunately, they confirmed that the current behavior is the best one. My guess is that doing such a modification is not trivial and, therefore, they decided not doing it. In fact, also the SQL trace files have a similar behavior. For example, via SQL trace, the execution plan for the UPDATE statement shown before is the following:</p>
<p><pre>Rows     Row Source Operation
-------  ---------------------------------------------------
      0  UPDATE  EMP (cr=7 pr=0 pw=0 time=0 us)
     14   TABLE ACCESS FULL EMP (cr=7 pr=0 pw=0 time=0 us cost=3 size=56 card=14)</pre></p>
<p>It is also interesting to note that while analyzing the code (probably for checking whether the change I proposed was doable) a developer discovered a bug. Based on the information I received (see bug number 6410147) it seems that in some situation the value of “A-Rows” is different than 0. But, since it is a bug, they fixed it.</p>
<p><strong>Update 2009-08-03</strong>: part 2 of this post is available <a href="/2009/08/a-rows-and-dml-statements-part-2/">here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2009/07/a-rows-and-dml-statements/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Wrong Information about Temporary Space Usage in V$SQL_PLAN_STATISTICS_ALL and DBMS_XPLAN Output</title>
		<link>http://antognini.ch/2009/05/wrong-information-about-temporary-space-usage/</link>
		<comments>http://antognini.ch/2009/05/wrong-information-about-temporary-space-usage/#comments</comments>
		<pubDate>Tue, 05 May 2009 00:00:20 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[10gR1]]></category>
		<category><![CDATA[10gR2]]></category>
		<category><![CDATA[11gR1]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[TOP]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=271</guid>
		<description><![CDATA[As you can read in the documentation, the columns MAX_TEMPSEG_SIZE and LAST_TEMPSEG_SIZE in the dynamic performance view V$SQL_WORKAREA provide information about the size of the temporary segment used for a specific workarea. The values are given in bytes. Let&#8217;s perform a test to check this information&#8230;

Create a test table that contains about 1MB of data:

SQL&#62; [...]]]></description>
			<content:encoded><![CDATA[<p>As you can read in the <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/dynviews_3.htm#sthref3287">documentation</a>, the columns MAX_TEMPSEG_SIZE and LAST_TEMPSEG_SIZE in the dynamic performance view V$SQL_WORKAREA provide information about the size of the temporary segment used for a specific workarea. The values are given in <em>bytes</em>. Let&#8217;s perform a test to check this information&#8230;</p>
<ul>
<li>Create a test table that contains about 1MB of data:</li>
</ul>
<p><pre>SQL&gt; CREATE TABLE t AS
  2  SELECT rownum AS id, dbms_random.string(&#039;p&#039;,1000) AS pad
  3  FROM dual
  4  CONNECT BY level &lt;= 1000;

SQL&gt; execute dbms_stats.gather_table_stats(user, &#039;t&#039;)</pre></p>
<ul>
<li>Setup the session to force the user process to spill into a temporary segment:</li>
</ul>
<p><pre>SQL&gt; ALTER SESSION SET workarea_size_policy = manual;
SQL&gt; ALTER SESSION SET sort_area_size = 524288;</pre></p>
<ul>
<li>Run test query including a sort operation (that spills to the temporary tablespace):</li>
</ul>
<p><pre>SQL&gt; SELECT id FROM t ORDER BY pad;</pre></p>
<ul>
<li>Check the amount of used temporary space by querying V$SQL_WORKAREA:</li>
</ul>
<p><pre>SQL&gt; SELECT max_tempseg_size, last_tempseg_size
  2  FROM v$sql_workarea
  3  WHERE (sql_id, child_number) IN (SELECT prev_sql_id, prev_child_number
  4                                   FROM v$session
  5                                   WHERE sid = sys_context(&#039;userenv&#039;,&#039;sid&#039;));

MAX_TEMPSEG_SIZE LAST_TEMPSEG_SIZE
---------------- -----------------
         2097152           2097152</pre></p>
<p>According to this information the size of the temporary space used to execute the query was 2MB. So far, so good.</p>
<p>Always according to the <a href="http://download.oracle.com/docs/cd/B28359_01/server.111/b28320/dynviews_3.htm#insertedID53">documentation</a> another dynamic performance view, V$SQL_PLAN_STATISTICS_ALL, should provide the same information (remember, V$SQL_PLAN_STATISTICS_ALL shows in a single view all the information provided by the views V$SQL_PLAN, V$SQL_PLAN_STATISTICS, and V$SQL_WORKAREA). Let&#8217;s check it&#8230;</p>
<ul>
<li>Run the same test query as before:</li>
</ul>
<p><pre>SQL&gt; SELECT id FROM t ORDER BY pad;</pre></p>
<ul>
<li>Check the amount of used memory by querying V$SQL_PLAN_STATISTICS_ALL:</li>
</ul>
<p><pre>SQL&gt; SELECT max_tempseg_size, last_tempseg_size
  2  FROM v$sql_plan_statistics_all
  3  WHERE (sql_id, child_number) IN (SELECT prev_sql_id, prev_child_number
  4                                   FROM v$session
  5                                   WHERE sid = sys_context(&#039;userenv&#039;,&#039;sid&#039;))
  6  AND max_tempseg_size IS NOT NULL;

MAX_TEMPSEG_SIZE LAST_TEMPSEG_SIZE
---------------- -----------------
            2048              2048</pre></p>
<p>Ups! According to this information the size of the temporary space used to execute the query was 2KB. Mhmm, something is not good&#8230; For this reason, at the end of 2007 I opened a service request about this issue. The support guy recognized the problem and opened a bug. Fine. For some unknown reasons (?) yesterday I was checking the status of few bugs. While doing so I noticed that this specific bug was closed few months ago with the status &#8220;Could Not Reproduce&#8221;! I don&#8217;t know you, but on my 64-bit Linux server I can reproduce it with at least 11.1.0.7.0, 11.1.0.6.0, 10.2.0.4.0, 10.2.0.3.0, 10.2.0.2.0, 10.2.0.1.0, 10.1.0.5.0, 10.1.0.4.0 and 10.1.0.3.0. Geez!</p>
<p>It is essential to note that also the package DBMS_XPLAN shows wrong information (here an example for the same query as before):</p>
<p><pre>SQL&gt; SELECT * FROM table(dbms_xplan.display_cursor(null,null,&#039;memstats last&#039;));

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
SQL_ID  ftb71b6926dtn, child number 0
-------------------------------------
SELECT id FROM t ORDER BY pad

Plan hash value: 961378228

---------------------------------------------------------------------------------
| Id  | Operation          | Name | E-Rows |  OMem |  1Mem | Used-Mem | Used-Tmp|
---------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |      |        |       |       |          |         |
|   1 |  SORT ORDER BY     |      |   1000 |  1152K|   562K|  529K (1)|    2048 |
|   2 |   TABLE ACCESS FULL| T    |   1000 |       |       |          |         |
---------------------------------------------------------------------------------</pre></p>
<p>The only good thing about the fact that Oracle is not willing to fix the bug is that my book, <a href="/top">Troubleshooting Oracle Performance</a>, does not need to be updated. In fact, at page 210, while describing the output of the package DBMS_XPLAN I wrote the following information:</p>
<ul>
<li>Used-Tmp: The amount of temporary space used by the operation during the last execution. This value must be multiplied by 1,024 to be consistent with the other memory utilization columns (for example, 32K means 32MB).</li>
<li>Max-Tmp: The maximum amount of temporary space used by the operation. This value has to be multiplied by 1,024 to be consistent with the other memory utilization columns (for example, 32K means 32MB).</li>
</ul>
<p><strong>ADDENDA</strong> (Mai 6, 2009): This post was noticed by an Oracle employee and, as a result, the bug was reopened. Thank you Greg!</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2009/05/wrong-information-about-temporary-space-usage/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Virtual Column-Based Partitioning Might Lead to Wrong Results</title>
		<link>http://antognini.ch/2009/02/virtual-column-based-partitioning-might-lead-to-wrong-results/</link>
		<comments>http://antognini.ch/2009/02/virtual-column-based-partitioning-might-lead-to-wrong-results/#comments</comments>
		<pubDate>Tue, 17 Feb 2009 06:53:31 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[11gR1]]></category>
		<category><![CDATA[Bug]]></category>
		<category><![CDATA[Partitioning]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=77</guid>
		<description><![CDATA[As of Oracle Database 11g it is possible to use a virtual column as partition key. In this post I do not want to discuss how it works and whether this is good or not&#8230; Instead, I would like to show you that the feature might lead to wrong results. 
First of all, I would [...]]]></description>
			<content:encoded><![CDATA[<p>As of Oracle Database 11g it is possible to use a virtual column as partition key. In this post I do not want to discuss how it works and whether this is good or not&#8230; Instead, I would like to show you that the feature might lead to wrong results. </p>
<p>First of all, I would like to show you a test where everything works fine. For that purpose, let&#8217;s create a table (notice the virtual column n2), insert one row into it, and gather the object statistics:</p>
<p><pre>SQL&gt; CREATE TABLE t (
  2    n1 NUMBER,
  3    n2 AS (CASE n1 WHEN 1 THEN 1 WHEN 2 THEN 2 ELSE 0 END) VIRTUAL
  4  )
  5  PARTITION BY LIST (n2) (
  6    PARTITION zero VALUES (0),
  7    PARTITION one VALUES (1),
  8    PARTITION two VALUES (2)
  9  )
 10  ENABLE ROW MOVEMENT;

SQL&gt; INSERT INTO t (n1) VALUES (1);

SQL&gt; COMMIT;

SQL&gt; execute dbms_stats.gather_table_stats(user,&#039;t&#039;)</pre></p>
<p>The aim of the following test is to check whether row movement works correctly. Hence, I update the column n1 to cause such a movement. To check whether row movement is performed or not, I display the content of the two involved partitions before and after the update statement. In addition, I also display the rowids (because of the movement the row should get a new rowid).</p>
<p><pre>SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (zero);

no rows selected

SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (one);

ROWID                      N1         N2
------------------ ---------- ----------
AAAE89AAEAAAAGNAAA          1          1

SQL&gt; UPDATE t SET n1 = 3;

SQL&gt; COMMIT;

SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (zero);

ROWID                      N1         N2
------------------ ---------- ----------
AAAE88AAEAAAAF9AAA          3          0

SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (one);

no rows selected</pre></p>
<p>The previous test was successful. Now, let me show you a situation that leads to wrong results :-(</p>
<p>To reproduce the bug I basically execute the same operations as before. The only difference is that seven columns are added before the columns n1 and n2 in the table. Hence, the test table is recreated with the following statements:</p>
<p><pre>SQL&gt; DROP TABLE t PURGE;

SQL&gt; CREATE TABLE t (
  2    d1 NUMBER,
  3    d2 NUMBER,
  4    d3 NUMBER,
  5    d4 NUMBER,
  6    d5 NUMBER,
  7    d6 NUMBER,
  8    d7 NUMBER,
  9    n1 NUMBER,
 10    n2 AS (CASE n1 WHEN 1 THEN 1 WHEN 2 THEN 2 ELSE 0 END) VIRTUAL
 11  )
 12  PARTITION BY LIST (n2) (
 13    PARTITION zero VALUES (0),
 14    PARTITION one VALUES (1),
 15    PARTITION two VALUES (2)
 16  )
 17  ENABLE ROW MOVEMENT;

SQL&gt; INSERT INTO t (n1) VALUES (1);

SQL&gt; COMMIT;

SQL&gt; execute dbms_stats.gather_table_stats(user,&#039;t&#039;)</pre></p>
<p>As before, I update the row to cause the movement and display the content of the two involved partitions before and after doing it.</p>
<p><pre>SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (zero);

no rows selected

SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (one);

ROWID                      N1         N2
------------------ ---------- ----------
AAAE9BAAEAAAAGNAAA          1          1

SQL&gt; UPDATE t SET n1 = 3;

SQL&gt; COMMIT;

SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (zero);

no rows selected

SQL&gt; SELECT rowid, n1, n2 FROM t PARTITION (one);

ROWID                      N1         N2
------------------ ---------- ----------
AAAE9BAAEAAAAGNAAA          3          0</pre></p>
<p>As you can see, the two queries after the update statement return wrong results. Also the rowid is the same. Hence, row movement was not performed. It goes without saying that also other queries might return wrong results. An example is the following:</p>
<p><pre>SQL&gt; SELECT rowid, n1, n2 FROM t WHERE n2 = 1;

ROWID                      N1         N2
------------------ ---------- ----------
AAAE9BAAEAAAAGNAAA          3          0</pre></p>
<p>By playing around with the number of columns and position of the columns n1 and n2, I found out that depending on the situation you might have correct results or wrong results.</p>
<p>Since I was able to reproduce the problem with several databases (both 11.1.0.6 and 11.1.0.7), last Friday I opened a service request. Now the issue is tracked as bug# 8258501.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2009/02/virtual-column-based-partitioning-might-lead-to-wrong-results/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Oracle AD4J Installation on Linux</title>
		<link>http://antognini.ch/2009/02/oracle-ad4j-installation-on-linux/</link>
		<comments>http://antognini.ch/2009/02/oracle-ad4j-installation-on-linux/#comments</comments>
		<pubDate>Fri, 13 Feb 2009 10:37:49 +0000</pubDate>
		<dc:creator>Christian Antognini</dc:creator>
				<category><![CDATA[Bug]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Oracle AD4J]]></category>

		<guid isPermaLink="false">http://antognini.ch/?p=70</guid>
		<description><![CDATA[Today I tried to install Oracle AD4J on a Linux server that I have at home. The installation procedure is really simple and fully described here. Unfortunately, when I tried to access the console for the first time (that access is one of the installation steps), the HTTP server returned an internal server error (500). [...]]]></description>
			<content:encoded><![CDATA[<p>Today I tried to install <a href="http://www.oracle.com/technology/products/oem/mgmt_solutions/apm.html">Oracle AD4J</a> on a Linux server that I have at home. The installation procedure is really simple and fully described <a href="http://download.oracle.com/docs/cd/B16240_01/doc/install.102/e11085/toc.htm">here</a>. Unfortunately, when I tried to access the console for the first time (that access is one of the installation steps), the HTTP server returned an internal server error (500). In the mod_jserv.log logfile I found the following error messages:</p>
<p><pre>[13/02/2009 10:06:38:079] (EMERGENCY) ajp12: can not connect to host 127.0.0.1:3501
[13/02/2009 10:06:38:181] (EMERGENCY) ajp12: connection fail
[13/02/2009 10:06:38:181] (ERROR) an error returned handling request via protocol &quot;ajpv12&quot;</pre></p>
<p>Mhmm&#8230; a listener should be available on port 3501. But, no such listener was available on my system (note that port 3500 is used for the HTTP listener):</p>
<p><pre>oracle@helicon:/u00/app/oracle/product/ad4j/ [rdbms11107] netstat -l --numeric-ports | grep 350[01]
tcp        0      0 *:3500                      *:*                         LISTEN</pre></p>
<p>A quick search in <a href="http://metalink.oracle.com">Metalink</a> revealed that at least another person has hit the same issue few days ago (see bug# 8235076). Since OSS is still working on it, I&#8217;ll wait to see what the findings are. In the mean time, I was able to successfully install it on my Windows laptop. </p>
<p>Anyway, if somebody of you managed to successfully install AD4J on Linux, please, let me know!</p>
<p><strong>ADDENDA</strong> (February 16th, 2009): Because of the comments of Charles and Michael I spent a bit more time looking at the problem. In fact, the first time I stopped immediately after seeing the bug in Metalink… I was lazy ;-). Hey, I try to optimize my worktime as well. Anyway, both suggested to manually start jserv. When I tried to do so, I received an error (at last). Based on it the problem was self explanatory! The java environment was causing the problem… In fact, with the default installation of CentOS 4.4 only the package java-1.4.2-gcj-compat was installed. After downloading and installing the most recent version of HotSpot (build 1.6.0_12-b04) the problem was solved.</p>
]]></content:encoded>
			<wfw:commentRss>http://antognini.ch/2009/02/oracle-ad4j-installation-on-linux/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

