﻿<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>老熊的三分地-Oracle、UNIX</title>
	<atom:link href="http://www.laoxiong.net/feed" rel="self" type="application/rss+xml" />
	<link>http://www.laoxiong.net</link>
	<description>老熊的生活、Oracle及UNIX技术、观点</description>
	<pubDate>Thu, 01 Jan 2009 07:13:01 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>别了，2008</title>
		<link>http://www.laoxiong.net/bye_2008.html</link>
		<comments>http://www.laoxiong.net/bye_2008.html#comments</comments>
		<pubDate>Wed, 31 Dec 2008 15:07:03 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle备份与恢复]]></category>

		<category><![CDATA[随笔]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=64</guid>
		<description><![CDATA[再过1小时，2008年就要过去了。
别了，2008
这一年里，发生了太多的事。
咱平民小百姓，不谈国家大事。谈谈自己的就好了。
2008年，在成都安定了下来。上班搞自己喜欢搞的ORACLE，下班回家陪陪父母、老婆和孩子。这日子，挺不错。
2009年，我会干什么呢？大家都会说计划没有变化快。看起来，我不用计划那么多事情了。唯一计划的是，为以后的发展储备更多的能量吧。
别了，2008
欢迎你，2009
]]></description>
			<content:encoded><![CDATA[<p>再过1小时，2008年就要过去了。<br />
别了，2008<br />
这一年里，发生了太多的事。<br />
咱平民小百姓，不谈国家大事。谈谈自己的就好了。</p>
<p>2008年，在成都安定了下来。上班搞自己喜欢搞的ORACLE，下班回家陪陪父母、老婆和孩子。这日子，挺不错。<br />
2009年，我会干什么呢？大家都会说计划没有变化快。看起来，我不用计划那么多事情了。唯一计划的是，为以后的发展储备更多的能量吧。</p>
<p>别了，2008<br />
欢迎你，2009</p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/bye_2008.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>全表扫描与buffer cache</title>
		<link>http://www.laoxiong.net/table_scan_and_buffer_cache.html</link>
		<comments>http://www.laoxiong.net/table_scan_and_buffer_cache.html#comments</comments>
		<pubDate>Tue, 23 Dec 2008 13:43:48 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle性能优化]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=63</guid>
		<description><![CDATA[QQ群里有位兄弟提出一个很有意思的问题，在一个db_cache_size为1.6G，几乎没有什么活动的数据库（版本为9.2.0.1)里面，一个简单的查询SELECT * FROM T，反复执行，这个查询的物理读始终很高。被查询的表不大，完全可以容纳在cache里面。根据直觉，频繁被读取的块，是应该cache在内存中的，不应该会有物理读，并且当时数据库没有其他的活动，cache中的块也不会被挤出去。
这个现象是违反直觉的，但注意，直觉的东西不一定不是正确的东西。那么为什么那个简单的SQL，在反复执行的情况下，怎么会有那么高的物理读呢？
这还得从Oracle的buffer cache管理说起。一个oracle进程在做全表扫描时，buffer会放置到LRU-AUX链表的尾端。如果在读块时，如果已经没有free buffer，那么进程就会查找可以被age out的块，这个查找过程是从LRU-AUX链表的尾端开始的。也就是说LRU-AUX链表尾端的buffer，总是第一个被替换的。
基于Oracle的这种LRU算法，我们假设，现在系统中已经没有free buffer，也就是buffer cache已经用完。实际上这种情况是最常见的，必竟现在的库相对于db_cache_size来说，总是大很多倍，buffer cache很快就会被填满。那么，在做全表扫描时，第1次多块读(multiblock read)的buffer会放置到LRU-AUX链表的尾端（不管这个buffer是从哪里得到的），第2次多块读时，需要buffer时，oracle也会从LRU-AUX链表的的尾端开始进行查找可以被替换的buffer，而刚好LRU-AUX链表的尾端的buffer正是上一次多块读时的buffer。也就是说前一次读到的块，很快就会被后面读的块替换掉了。
因此，不难理解，为什么在数据库活动很少时，反复扫描同一个表（这里不是同时扫描），其物理读仍然很高。并不是我们直觉的那样，这个表已经很“热”，应该全部在内存中命中。
下面我们通过一个测试来验证我们的推断。
测试环境：
Oracle 10.2.0.3 32Bit for Linux
我们设置如下的参数，以便让buffer cache的大小在我们控制的范围内：
SQL> alter system set shared_pool_size=100m;
System altered.
SQL> alter system set db_cache_size=30m;
System altered.
SQL> alter system set sga_target=200m;

再建两个测试表T1，T2，使每一个表的块只能放置1行数据。
SQL> create table t1 ( a int,b char(2000),c char(2000),d char(1000));
Table created.
SQL> create table t2 ( a int,b char(2000),c char(2000),d char(1000));
Table created.
SQL> insert into t1 values (1,&#8217;a',&#8217;b',&#8217;c');
1 [...]]]></description>
			<content:encoded><![CDATA[<p>QQ群里有位兄弟提出一个很有意思的问题，在一个db_cache_size为1.6G，几乎没有什么活动的数据库（版本为9.2.0.1)里面，一个简单的查询SELECT * FROM T，反复执行，这个查询的物理读始终很高。被查询的表不大，完全可以容纳在cache里面。根据直觉，频繁被读取的块，是应该cache在内存中的，不应该会有物理读，并且当时数据库没有其他的活动，cache中的块也不会被挤出去。</p>
<p>这个现象是违反直觉的，但注意，直觉的东西不一定不是正确的东西。那么为什么那个简单的SQL，在反复执行的情况下，怎么会有那么高的物理读呢？</p>
<p>这还得从Oracle的buffer cache管理说起。一个oracle进程在做全表扫描时，buffer会放置到LRU-AUX链表的尾端。如果在读块时，如果已经没有free buffer，那么进程就会查找可以被age out的块，这个查找过程是从LRU-AUX链表的尾端开始的。也就是说LRU-AUX链表尾端的buffer，总是第一个被替换的。</p>
<p>基于Oracle的这种LRU算法，我们假设，现在系统中已经没有free buffer，也就是buffer cache已经用完。实际上这种情况是最常见的，必竟现在的库相对于db_cache_size来说，总是大很多倍，buffer cache很快就会被填满。那么，在做全表扫描时，第1次多块读(multiblock read)的buffer会放置到LRU-AUX链表的尾端（不管这个buffer是从哪里得到的），第2次多块读时，需要buffer时，oracle也会从LRU-AUX链表的的尾端开始进行查找可以被替换的buffer，而刚好LRU-AUX链表的尾端的buffer正是上一次多块读时的buffer。也就是说前一次读到的块，很快就会被后面读的块替换掉了。</p>
<p>因此，不难理解，为什么在数据库活动很少时，反复扫描同一个表（这里不是同时扫描），其物理读仍然很高。并不是我们直觉的那样，这个表已经很“热”，应该全部在内存中命中。</p>
<p>下面我们通过一个测试来验证我们的推断。</p>
<p>测试环境：<br />
Oracle 10.2.0.3 32Bit for Linux<br />
我们设置如下的参数，以便让buffer cache的大小在我们控制的范围内：</p>
<blockquote><p>SQL> alter system set shared_pool_size=100m;</p>
<p>System altered.</p>
<p>SQL> alter system set db_cache_size=30m;</p>
<p>System altered.</p>
<p>SQL> alter system set sga_target=200m;</p></blockquote>
<p><span id="more-63"></span><br />
再建两个测试表T1，T2，使每一个表的块只能放置1行数据。</p>
<blockquote><p>SQL> create table t1 ( a int,b char(2000),c char(2000),d char(1000));</p>
<p>Table created.</p>
<p>SQL> create table t2 ( a int,b char(2000),c char(2000),d char(1000));</p>
<p>Table created.</p>
<p>SQL> insert into t1 values (1,&#8217;a',&#8217;b',&#8217;c');</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> alter table t1 minimize records_per_block;</p>
<p>Table altered.</p>
<p>SQL> insert into t2 values (1,&#8217;a',&#8217;b',&#8217;c');</p>
<p>1 row created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> alter table t2 minimize records_per_block;</p>
<p>Table altered.</p></blockquote>
<p>向这两个表中插入3999行数据，与上面插入的1行一起分别共计4000行。</p>
<blockquote><p>SQL> insert into t1 select rownum+1,&#8217;a',&#8217;b',&#8217;c&#8217; from dba_objects where rownum< =3999;</p>
<p>3999 rows created.</p>
<p>SQL> insert into t2 select rownum+1,&#8217;a',&#8217;b',&#8217;c&#8217; from dba_objects where rownum< =3999;</p>
<p>3999 rows created.</p>
<p>SQL> commit;</p>
<p>Commit complete.</p>
<p>SQL> col segment_name for a20<br />
SQL> select segment_name,blocks from dba_segments where owner=user and segment_name in (&#8217;T1&#8242;,&#8217;T2&#8242;);</p>
<p>SEGMENT_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BLOCKS<br />
--------------------&nbsp;----------<br />
T2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4096<br />
T1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4096</p></blockquote>
<p>可以看到这两个表都有4096个块，每个表32MB。<br />
刷新buffer_cache，保证buffer cache中没有任何这两个表的块。</p>
<blockquote><p>SQL> select object_name,data_object_id from dba_objects where owner=user and object_name in (&#8217;T1&#8242;,&#8217;T2&#8242;);</p>
<p>OBJECT_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DATA_OBJECT_ID<br />
--------------------&nbsp;--------------<br />
T1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;52416<br />
T2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;52417<br />
SQL> alter system flush buffer_cache;</p>
<p>System altered.</p>
<p>SQL> select count(*) from x$bh where obj in (52416,52417) and state<>0;</p>
<p>  COUNT(*)<br />
----------<br />
         0</p></blockquote>
<p>查询T1表，让T1表中的所有块填充到buffer cache中，并统计X$BH中各状态的合计：</p>
<blockquote><p>SQL> select count(*) from t1;</p>
<p>  COUNT(*)<br />
----------<br />
      4000<br />
SQL> select set_ds,<br />
  2         decode(state,0,&#8217;free&#8217;,1,&#8217;xcur&#8217;,2,&#8217;scur&#8217;,3,&#8217;cr&#8217;,4,&#8217;read&#8217;,5,&#8217;mrec&#8217;,<br />
  3             6,&#8217;irec&#8217;,7,&#8217;write&#8217;,8,&#8217;pi&#8217;) state,<br />
  4         count(*) cnt<br />
  5    from x$bh<br />
  6   group by set_ds, state<br />
  7   order by 1, 2;</p>
<p>SET_DS&nbsp;&nbsp;&nbsp;STATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CNT<br />
--------&nbsp;-----&nbsp;----------<br />
2C5430B4&nbsp;cr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5<br />
2C5430B4&nbsp;free&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;72<br />
2C5430B4&nbsp;xcur&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6872</p></blockquote>
<p>用TEST用户连接产生另一个会话（以下称之为会话2），在会话2中查询T2表：</p>
<blockquote><p>SQL> connect test/test<br />
Connected.<br />
SQL> set autot on statistics<br />
SQL> select count(*) from sys.t2;</p>
<p>  COUNT(*)<br />
----------<br />
      4000<br />
Statistics<br />
----------------------------------------------------------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;154&nbsp;&nbsp;recursive&nbsp;calls<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;db&nbsp;block&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4026&nbsp;&nbsp;consistent&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4003&nbsp;&nbsp;physical&nbsp;reads<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;redo&nbsp;size<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;411&nbsp;&nbsp;bytes&nbsp;sent&nbsp;via&nbsp;SQL*Net&nbsp;to&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;400&nbsp;&nbsp;bytes&nbsp;received&nbsp;via&nbsp;SQL*Net&nbsp;from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;SQL*Net&nbsp;roundtrips&nbsp;to/from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;sorts&nbsp;(memory)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(disk)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;rows&nbsp;processed
</p></blockquote>
<p>在会话2中反复多次查询T2表，发现T2表的物理读数几乎不再变化：</p>
<blockquote><p>SQL> /</p>
<p>  COUNT(*)<br />
----------<br />
      4000</p>
<p>Statistics<br />
----------------------------------------------------------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;recursive&nbsp;calls<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;db&nbsp;block&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4009&nbsp;&nbsp;consistent&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3682&nbsp;&nbsp;physical&nbsp;reads<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;redo&nbsp;size<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;411&nbsp;&nbsp;bytes&nbsp;sent&nbsp;via&nbsp;SQL*Net&nbsp;to&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;400&nbsp;&nbsp;bytes&nbsp;received&nbsp;via&nbsp;SQL*Net&nbsp;from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;SQL*Net&nbsp;roundtrips&nbsp;to/from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(memory)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(disk)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;rows&nbsp;processed</p>
<p>SQL> /</p>
<p>  COUNT(*)<br />
----------<br />
      4000</p>
<p>Statistics<br />
----------------------------------------------------------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;recursive&nbsp;calls<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;db&nbsp;block&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4009&nbsp;&nbsp;consistent&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3712&nbsp;&nbsp;physical&nbsp;reads<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;redo&nbsp;size<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;411&nbsp;&nbsp;bytes&nbsp;sent&nbsp;via&nbsp;SQL*Net&nbsp;to&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;400&nbsp;&nbsp;bytes&nbsp;received&nbsp;via&nbsp;SQL*Net&nbsp;from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;SQL*Net&nbsp;roundtrips&nbsp;to/from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(memory)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(disk)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;rows&nbsp;processed</p>
<p>SQL> /</p>
<p>  COUNT(*)<br />
----------<br />
      4000</p>
<p>Statistics<br />
----------------------------------------------------------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;recursive&nbsp;calls<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;db&nbsp;block&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4009&nbsp;&nbsp;consistent&nbsp;gets<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3712&nbsp;&nbsp;physical&nbsp;reads<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;redo&nbsp;size<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;411&nbsp;&nbsp;bytes&nbsp;sent&nbsp;via&nbsp;SQL*Net&nbsp;to&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;400&nbsp;&nbsp;bytes&nbsp;received&nbsp;via&nbsp;SQL*Net&nbsp;from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2&nbsp;&nbsp;SQL*Net&nbsp;roundtrips&nbsp;to/from&nbsp;client<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(memory)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;sorts&nbsp;(disk)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;rows&nbsp;processed</p></blockquote>
<p>在会话1中，对x$bh按state进行状态，其结果也趋于稳定：</p>
<blockquote><p>SET_DS&nbsp;&nbsp;&nbsp;STATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CNT<br />
--------&nbsp;-----&nbsp;----------<br />
2B9430B4&nbsp;cr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6<br />
2B9430B4&nbsp;free&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;72<br />
2B9430B4&nbsp;xcur&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10401</p></blockquote>
<p>如果查询T1表，会发现，T1表不再产生逻辑读，这是因为T1表开始已经全部装入到buffer cache中。</p>
<p>因此，这里可以得到一个结论，如果buffer cache有足够的剩余空间，使一个全表扫描所读到的所有块全部装入到buffer cache，否则全表扫描产生的物理读仍然是相当的高，不管这个表被扫描到多少次。</p>
<p>虽然提出此问题的网友使用的Oracle为9.2.0.1，在这个版本下的测试，可以得到同样的结果。</p>
<p>即使是多个进程并发扫描同一个表，除非一个多块读操作读进buffer cache中的块，在age out之前被另一个多块读操作读到，那么多个进程对同一个表进行全表扫描，产生的物理读仍然是非常高的。</p>
<p>而如果一个多块读操作读进buffer cache中的块，age out之前被另一个单块读操作读到，那结果也许更糟糕，这导致一个块被移到LRU-MAIN链表中，被age out的机会相对减少，但是正是由于一个块没有被age out，下一次相同范围的多块读，将不得不分成两次多块读。</p>
<p>对于一个频繁全表扫描的表，如果SQL不能优化，则应该尽量放置到KEEP BUFFER中，这将显著减少物理读的数量。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/table_scan_and_buffer_cache.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>DBMS_STATS、ANALYZE以及Global Statistics</title>
		<link>http://www.laoxiong.net/dbms_stats_and_analyze_and_global_statistics.html</link>
		<comments>http://www.laoxiong.net/dbms_stats_and_analyze_and_global_statistics.html#comments</comments>
		<pubDate>Mon, 15 Dec 2008 15:52:09 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle性能优化]]></category>

		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=61</guid>
		<description><![CDATA[什么是global statistics？
大家都知道，dbms_stats是Oracle 9i及后续的版本中用于收集优化器统计信息的包，虽然analyze命令也一直可用，但是现在已经不推荐使用analyze来收集统计信息，而是使用dbms_stats。二者之间一个很大的不同，也是dbms_stats一个很突出的优点就是能够正确收集分区表的统计信息，换言之就是global statistics。而analyze命令只会收集最低层次对象的统计信息，然后推导和汇总出高一级的统计信息，如分区表只会收集分区信息，然后再汇总所有分区的统计信息，得到表一级的统计信息。
那什么是global statistics？简单地说global statistics就是指直接从对象本身这一级收集到的统计信息，而不是从下一级对象“推导”或“汇总”出来的统计信息。比如，表的global statistics指直接通过表收集到的统计信息，而不是从分区收集的统计信息进行汇总或推导出的。同样，分区的global statistics是指直接通过分区收集到的统计信息，而不是从子分区收集的统计信息进行汇总或推导出的。global statistics对优化器来说是非常重要的，一个SQL，除非其查询条件限定了数据只在部分分区上，否则在大多数情况下需要global statistics才能得到正确的执行计划。
有的统计值可以从对象的下一级对象进行汇总后得到，比如表的总行数，可以通过各分区的行数相加得到。但有的统计值则不能从下一级对象得到，比如列上的唯一值数量(distinct value）以及密度值（density）。
怎样收集global statistics？
global statistics只能通过dbms_stats包来收集。注意，用analyze命令得到的统计信息，虽然也会有表一级的统计值，但是，那些值是从分区或子分区推导和汇总出来的，是不精确的。后面的实验中，将会验证这一点。
使用dbms_stats收集统计信息时，参数granularity（比如gather_table_stats过程） 指定了哪个级别上的统计信息会被收集：

Global -- Table （表）
Partition -- Partition （分区）
SubPartition -- SubPartition  （子分区）
Default -- Table + Partition （表+分区）
All -- Table + Partition + Subpartit （表+分区+子分区）

比如，要在一个做为子分区的表上，以&#8217;ALL&#8217;级别收集统计信息时，会收集”表+分区+子分区“上的统计信息，相当于需要执行下面的三类SQL：

select &#8230;. from table 
select &#8230;. from table (partition P1) -- 在每个分区上都重复一次
select &#8230;. from table (subpartition SP1) -- 在每个子分区上重复一次

可以看到，dbms_stats需要比analyze命令更多的时间来进行统计信息的收集。对于有子分区的表，dbms_stats至少要多花三倍的时间。

怎样查看表是否收集了global statistics？
统计信息(下面主要描述表和分区，不涉及索引）一般是通过查看下列视图来检查的：

表的统计信息：
[DBA&#124;ALL&#124;USER]_TABLES
[DBA&#124;ALL&#124;USER]_TAB_COL_STATISTICS [...]]]></description>
			<content:encoded><![CDATA[<p><strong>什么是global statistics？</strong></p>
<p>大家都知道，dbms_stats是Oracle 9i及后续的版本中用于收集优化器统计信息的包，虽然analyze命令也一直可用，但是现在已经不推荐使用analyze来收集统计信息，而是使用dbms_stats。二者之间一个很大的不同，也是dbms_stats一个很突出的优点就是能够<strong>正确收集分区表的统计信息</strong>，换言之就是global statistics。而analyze命令只会收集最低层次对象的统计信息，然后推导和汇总出高一级的统计信息，如分区表只会收集分区信息，然后再汇总所有分区的统计信息，得到表一级的统计信息。</p>
<p>那什么是global statistics？简单地说global statistics就是指直接从对象本身这一级收集到的统计信息，而不是从下一级对象“推导”或“汇总”出来的统计信息。比如，表的global statistics指直接通过表收集到的统计信息，而不是从分区收集的统计信息进行汇总或推导出的。同样，分区的global statistics是指直接通过分区收集到的统计信息，而不是从子分区收集的统计信息进行汇总或推导出的。global statistics对优化器来说是非常重要的，一个SQL，除非其查询条件限定了数据只在部分分区上，否则在大多数情况下需要global statistics才能得到正确的执行计划。</p>
<p>有的统计值可以从对象的下一级对象进行汇总后得到，比如表的总行数，可以通过各分区的行数相加得到。但有的统计值则不能从下一级对象得到，比如列上的唯一值数量(distinct value）以及密度值（density）。</p>
<p><strong>怎样收集global statistics？</strong></p>
<p>global statistics只能通过dbms_stats包来收集。<strong>注意，用analyze命令得到的统计信息，虽然也会有表一级的统计值，但是，那些值是从分区或子分区推导和汇总出来的，是不精确的。</strong>后面的实验中，将会验证这一点。</p>
<p>使用dbms_stats收集统计信息时，参数granularity（比如gather_table_stats过程） 指定了哪个级别上的统计信息会被收集：</p>
<ul>
<li>Global -- Table （表）</li>
<li>Partition -- Partition （分区）</li>
<li>SubPartition -- SubPartition  （子分区）</li>
<li>Default -- Table + Partition （表+分区）</li>
<li>All -- Table + Partition + Subpartit （表+分区+子分区）</li>
</ul>
<p>比如，要在一个做为子分区的表上，以&#8217;ALL&#8217;级别收集统计信息时，会收集”表+分区+子分区“上的统计信息，相当于需要执行下面的三类SQL：</p>
<ul>
<li>select &#8230;. from table </li>
<li>select &#8230;. from table (partition P1) -- 在每个分区上都重复一次</li>
<li>select &#8230;. from table (subpartition SP1) -- 在每个子分区上重复一次</li>
</ul>
<p>可以看到，dbms_stats需要比analyze命令更多的时间来进行统计信息的收集。对于有子分区的表，dbms_stats至少要多花三倍的时间。<br />
<span id="more-61"></span></p>
<p><strong>怎样查看表是否收集了global statistics？</strong></p>
<p>统计信息(下面主要描述表和分区，不涉及索引）一般是通过查看下列视图来检查的：</p>
<ul>
<li>表的统计信息：</li>
<p>[DBA|ALL|USER]_TABLES<br />
[DBA|ALL|USER]_TAB_COL_STATISTICS </p>
<li>分区的统计信息：</li>
<p>[DBA|ALL|USER]_TAB_PARTITIONS<br />
[DBA|ALL|USER]_PART_COL_STATISTICS </p>
<li>子分区的统计信息：</li>
<p>[DBA|ALL|USER]_TAB_SUBPARTITIONS<br />
[DBA|ALL|USER]_SUBPART_COL_STATISTICS </ul>
<p>在以上的视图中，如果GLOBAL_STATS列值为”YES“，表示该级对象上收集了global statistics，而值为”NO“则表示没有收集global statistics。</p>
<p>下面用一些实验来更深入地验证dbms_stats,analyze以及global statistics三者之间的联系。测试环境为Linux AS4上的Oracle 10.2.0.3。注意不同的Oracle可能有不同的行为。</p>
<p>我们先用下面的SQL创建一个测试表，这个表有2个分区，每个分区有2个子分区：</p>
<blockquote><p>CREATE&nbsp;TABLE&nbsp;T3(i&nbsp;number,&nbsp;&nbsp;p&nbsp;number,sp&nbsp;number)<br />
PARTITION&nbsp;BY&nbsp;RANGE(p)<br />
SUBPARTITION&nbsp;BY&nbsp;HASH(sp)&nbsp;SUBPARTITIONS&nbsp;2&nbsp;<br />
(<br />
&nbsp;&nbsp;PARTITION&nbsp;q1&nbsp;VALUES&nbsp;LESS&nbsp;THAN(3)&nbsp;TABLESPACE&nbsp;USERS,<br />
&nbsp;&nbsp;&nbsp;PARTITION&nbsp;q2&nbsp;VALUES&nbsp;LESS&nbsp;THAN(MAXVALUE)&nbsp;TABLESPACE&nbsp;USERS<br />
);</p>
<p>declare&nbsp;<br />
&nbsp;&nbsp;i&nbsp;number;&nbsp;<br />
begin&nbsp;<br />
&nbsp;&nbsp;for&nbsp;i&nbsp;in&nbsp;1..100000&nbsp;loop&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;insert&nbsp;into&nbsp;T3&nbsp;values(i,mod(i,7),&nbsp;mod(i,8));&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;mod(i,&nbsp;1000)&nbsp;=&nbsp;0)&nbsp;then&nbsp;commit;&nbsp;end&nbsp;if;&nbsp;<br />
&nbsp;&nbsp;end&nbsp;loop;&nbsp;<br />
for&nbsp;i&nbsp;in&nbsp;1..50000&nbsp;loop&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;insert&nbsp;into&nbsp;T3&nbsp;values(i,mod(i,7),&nbsp;mod(i,8)+5);&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if(&nbsp;mod(i,&nbsp;1000)&nbsp;=&nbsp;0)&nbsp;then&nbsp;commit;&nbsp;end&nbsp;if;&nbsp;<br />
&nbsp;&nbsp;end&nbsp;loop;&nbsp;<br />
end;&nbsp;<br />
/
</p></blockquote>
<p>我们向测试表中插入15W行数据。I列有100,000个不同的值，P列有7个不同的值，SP列有13个不同的值。为了能够方便地查看收集的统计信息，我们使用了一段来自Metalink的sql代码，<a href="http://www.laoxiong.net/wp-content/uploads/2008/12/sosi.sql">点击此处下载此代码文件sosi.sql</a>。</p>
<p>首先用@sosi可以看到，T3没有任何统计信息存在。<br />
使用analyze table t3 compute statistics;收集T3表的统计信息，可以看到如下的统计信息（由于版面原因，去除了一些与本文无关的信息）：</p>
<blockquote><p>SQL> analyze table t3 compute statistics;<br />
SQL> @sosi<br />
SQL> set echo off</p>
<p>Tables owned by TEST<br />
------------------------------<br />
T3</p>
<p>Please enter Name of Table Owner (Null = TEST):<br />
Please enter Table Name to show Statistics for: T3</p>
<p>***********<br />
Table Level<br />
***********</p>
<p>Table&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Empty&nbsp;Average&nbsp;Chain&nbsp;Average&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;of&nbsp;Rows&nbsp;&nbsp;&nbsp;Blocks&nbsp;Blocks&nbsp;&nbsp;&nbsp;Space&nbsp;Count&nbsp;Row&nbsp;Len&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
-------------&nbsp;--------&nbsp;------&nbsp;-------&nbsp;-----&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
T3&nbsp;&nbsp;&nbsp;&nbsp;150,000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;328&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;921&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0 </p>
<p>Column&nbsp;Column&nbsp;&nbsp;&nbsp;&nbsp;Distinct&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;Number&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;Details&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;Density&nbsp;Buckets&nbsp;&nbsp;Nulls&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
------&nbsp;------------------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMBER(22)&nbsp;&nbsp;59,845&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMBER(22)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMBER(22)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>***************<br />
Partition Level<br />
***************<br />
Partition&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Empty&nbsp;Average&nbsp;Chain&nbsp;Average&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;Rows&nbsp;&nbsp;&nbsp;Blocks&nbsp;Blocks&nbsp;&nbsp;&nbsp;Space&nbsp;Count&nbsp;Row&nbsp;Len&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;-------&nbsp;--------&nbsp;------&nbsp;-------&nbsp;-----&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;64,285&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;878&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;85,715&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;190&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;18&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;954&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</p>
<p>Partition&nbsp;Column&nbsp;Distinct&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;Number&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;Density&nbsp;Buckets&nbsp;&nbsp;Nulls&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;------&nbsp;--------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;44,878&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;59,844&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
***************<br />
SubPartition Level<br />
***************</p>
<p>Partition&nbsp;SubPartition&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Empty&nbsp;Average&nbsp;Average&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;Rows&nbsp;&nbsp;&nbsp;Blocks&nbsp;Blocks&nbsp;&nbsp;&nbsp;Space&nbsp;Row&nbsp;Len&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;------------&nbsp;-------&nbsp;--------&nbsp;------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;992&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;26,785&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;902&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;26,785&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;928&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;14&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;861&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;</p>
<p>Partition&nbsp;SubPartition&nbsp;&nbsp;&nbsp;&nbsp;Column&nbsp;&nbsp;Distinct&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;Number&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;Density&nbsp;Buckets&nbsp;&nbsp;Nulls&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;---------------&nbsp;-------&nbsp;--------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;24,106&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;26,785&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;26,785&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;26,785&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32,142&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32,144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;42,858&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50,000
</p></blockquote>
<p>由上面的表可以看到，analyze只是收集了sub partition的统计信息，然后经过汇总和推导得到了partition和table级别的统计信息。global_stats列值均为&#8221;NO&#8221;。在表级的I字段的统计信息上看到，I的唯一值个数为59,845，而实际的值应该为100,000，这里差距是比较大的；SP的唯一值个数为8，而实际的值应该为13。</p>
<p>下面再将统计信息删除，然后使用dbms_stats重新收集统计信息：</p>
<blockquote><p>
SQL> exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;ALL&#8217;);<br />
SQL> @sosi<br />
SQL> set echo off</p>
<p>Tables owned by TEST<br />
------------------------------<br />
T3</p>
<p>Please enter Name of Table Owner (Null = TEST):<br />
Please enter Table Name to show Statistics for: T3</p>
<p>***********<br />
Table Level<br />
***********</p>
<p>Table&nbsp;&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Empty&nbsp;Average&nbsp;Chain&nbsp;Average&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;of&nbsp;Rows&nbsp;&nbsp;&nbsp;Blocks&nbsp;Blocks&nbsp;&nbsp;&nbsp;Space&nbsp;Count&nbsp;Row&nbsp;Len&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
------&nbsp;-------&nbsp;--------&nbsp;------&nbsp;-------&nbsp;-----&nbsp;-------&nbsp;------&nbsp;------&nbsp;-------&nbsp;<br />
T3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;150,000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;328&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;150,000&nbsp;</p>
<p>Column&nbsp;Column&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Distinct&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;Number&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;&nbsp;Sample&nbsp;Date<br />
Name&nbsp;&nbsp;&nbsp;Details&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;Density&nbsp;Buckets&nbsp;&nbsp;Nulls&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;MM-DD-YYYY<br />
------&nbsp;-----------&nbsp;--------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;-------&nbsp;----------<br />
I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMBER(22)&nbsp;&nbsp;&nbsp;100,000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;150,000&nbsp;12-15-2008<br />
P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMBER(22)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,497&nbsp;12-15-2008<br />
SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NUMBER(22)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,497&nbsp;12-15-2008<br />
***************<br />
Partition Level<br />
***************</p>
<p>Partition&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Empty&nbsp;Average&nbsp;Chain&nbsp;Average&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;Rows&nbsp;&nbsp;&nbsp;Blocks&nbsp;Blocks&nbsp;&nbsp;&nbsp;Space&nbsp;Count&nbsp;Row&nbsp;Len&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;-------&nbsp;--------&nbsp;------&nbsp;-------&nbsp;-----&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;64,285&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;138&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;64,285&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;85,715&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;190&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;85,715&nbsp;</p>
<p>Partition&nbsp;Column&nbsp;&nbsp;Distinct&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;Number&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;Density&nbsp;Buckets&nbsp;&nbsp;Nulls&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;-------&nbsp;--------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;42,857&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;64,285&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,584&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,584&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;57,143&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;85,715&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,443&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,443 </p>
<p>***************<br />
SubPartition Level<br />
***************</p>
<p>Partition&nbsp;SubPartition&nbsp;&nbsp;&nbsp;Number&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Empty&nbsp;Average&nbsp;Average&nbsp;Global&nbsp;User&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;of&nbsp;Rows&nbsp;&nbsp;&nbsp;Blocks&nbsp;Blocks&nbsp;&nbsp;&nbsp;Space&nbsp;Row&nbsp;Len&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
---------&nbsp;-------------&nbsp;-------&nbsp;--------&nbsp;------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;-----&nbsp;------&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;26,595&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;58&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,461&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;110&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;80&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;10&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;37,500 </p>
<p>Partition&nbsp;&nbsp;SubPartition&nbsp;&nbsp;&nbsp;&nbsp;Column&nbsp;&nbsp;Distinct&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number&nbsp;Number&nbsp;Global&nbsp;User&nbsp;&nbsp;&nbsp;Sample&nbsp;<br />
Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Values&nbsp;Density&nbsp;Buckets&nbsp;&nbsp;Nulls&nbsp;Stats&nbsp;&nbsp;Stats&nbsp;&nbsp;&nbsp;&nbsp;Size&nbsp;<br />
----------&nbsp;---------------&nbsp;-------&nbsp;--------&nbsp;-------&nbsp;-------&nbsp;------&nbsp;------&nbsp;------&nbsp;------&nbsp;<br />
Q1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;26,084&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,461&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,461&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP29&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,461&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32,142&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;37,500&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,459&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP30&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,459&nbsp;<br />
Q2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;32,144&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;35,715&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,605&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,605&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;I&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;42,858&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;50,000&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;P&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,500&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SYS_SUBP32&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0&nbsp;YES&nbsp;&nbsp;&nbsp;&nbsp;NO&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5,500
</p></blockquote>
<p>从上面的统计信息可以看到，不管是在partition级，还是在table级，I列和SP列的唯一值个数都得到了正确的值。在三种级别（table,partition,subpartition）上，global_stats列值都为“YES”，表示三个级别收集的都是global statistics。</p>
<p>将统计信息删除，使用exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;SUBPARTITION&#8217;);<br />
收集子分区级别上的统计信息（此处不再列出具体的统计信息数据），则子分区统计信息中的global_stats值为&#8221;YES&#8221;，而分区和表级统计信息中的global_stats值为”NO&#8221;，这两级的统计数据则是由子分区级统计信息汇总和推导得出。<br />
而使用exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;PARTITION&#8217;);收集分区级上的统计信息，则子分区没有统计信息，表级的统计信息也是由分区级统计信息推导和汇总而来。<br />
而在缺省情况下，即granularity参数为default值时，分区和表都有global statistics，而子分区级没有任何统计信息 。</p>
<p>在以上的测试中，在进行新的统计信息收集之前，都是先删除了原来的统计信息。但是如果我们在收集统计信息之前没有删除原来的统计数据，并且不同的统计策略，会有不同的影响。但大部分都是很不好的影响，容易造成统计信息的不准确。比如：</p>
<ul>
<li>使用dbms_stats以granularity=&#8217;ALL&#8217;收集统计信息，删除一部分数据之后，再以更低级别的粒度收集统计数据：</li>
</ul>
<blockquote><p>SQL> exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;ALL&#8217;);<br />
SQL> delete from t3 where i&lt;3000;<br />
SQL> commit;<br />
SQL> exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;PARTITION&#8217;);<br />
SQL>
</p></blockquote>
<p>然后对比统计信息，可以发现，<strong>表级和子分区级仍然保留着原来的过时的统计信息。</strong>综合其他的几个测试（此处不再列出），我们可以得到这个结论：<strong>使用dbms_stats收集统计信息，粒度（granularity）为较低级别时，更低级别的统计信息保持不变，而高级别的统计信息由收集的这一级别的统计信息推导和汇总得出，但不能跨级别推导和汇总。但如果高级别的统计信息之前是global statistics，则那一级别的统计信息保持不变。analyze始终是在子分区级别收集统计信息，其高级别统计信息的推导和汇总的行为与dbms_stats一样。</strong>比如，现在表级的统计信息global_stats为NO，分区级的统计信息global_stats为YES，使用SUBPARTITION级别或使用analyze命令分析后，分区级的统计信息仍然是原来的统计信息，而表级的统计信息其global_stats为NO，但由于不能跨级推导和汇总，所以表这一级的统计信息仍然是原来的统计信息。</p>
<ul>
<li>使用dbms_stats以granularity=&#8217;PARTITION&#8217;收集统计信息，然后使用analyze删除统计信息：</li>
</ul>
<blockquote><p>SQL> exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;PARTITION&#8217;);<br />
SQL> analyze table t3 delete statistics;<br />
SQL> exec dbms_stats.gather_table_stats(ownname=>user,tabname=>&#8217;T3&#8242;,granularity=>&#8217;ALL&#8217;);<br />
SQL> analyze table t3 delete statistics;
</p></blockquote>
<p>执行上面的命令序列之后，我们可以发现，<strong>analyze ..delete statistics命令总是会删除子分区的统计信息，但分区级和表级，如果有global statistics统计信息，则不会删除。并且不能跨级删除，比如分区有global statistics，由表级没有global statistics，表级的统计信息也不会被删除。</strong>综合其他几个测试，也可以得到：如果某一级（partition,subpartition）上有统计信息，那么比它更高的所有级别上都会有统计信息。</p>
<ul>
<li>各种情况下使用dbms_stats.delete_table_stats删除统计信息，可以发现：</li>
</ul>
<p><strong>dbms_stats.delete_table_stats总是可以删除表上所有的三个级别的统计信息。</strong></p>
<ul>
<li>使用analyze命令收集的统计信息，有如下特点：</li>
<p><strong>analyze命令收集的统计信息，global_stats总是为&#8221;NO“。</strong></p>
<p>综合以上测试和得到的结果，总结出我们在收集优化统计信息需要注意以下几个方面：
</ul>
<ul>
<li>分区表的统计信息使用dbms_stats包中的过程，这样才能收集global statistics。</li>
<li>删除表的统计信息使用dbms_stats包中的过程，analyze命令删除统计信息，可能不是你想要的结果，因为有可能部分统计信息并没有被删除。</li>
<li>
收集统计信息时，使用一致的granularity参数，比如开始用ALL，过一段时间用DEFAULT或PARTITION，这样得出的结果，在某些级别上的统计信息是过时的，不准确的。</li>
<li>由于analyze命令只在最低一级收集统计信息，而高一级的统计信息是下级统计信息汇总和推导而来。因此不要将analyze命令与dbms_stats混合使用于同一张表上，其原因如同上一条。</li>
</ul>
<p>本文涉及到的内容，只有表（并且是普通的HEAP表），不包括索引。也没有涉及到直方图。本文部分内容来源于Metalink Note ID：236935.1 ”Global statistics - An Explanation“</p>
<p>如果需要深入研究analyze和dbms_stats，感兴趣的可以使用sql trace或10046事件来跟踪二者的行为。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/dbms_stats_and_analyze_and_global_statistics.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>利用复合索引解决性能问题一例</title>
		<link>http://www.laoxiong.net/composite_index_overcome_performance_problem.html</link>
		<comments>http://www.laoxiong.net/composite_index_overcome_performance_problem.html#comments</comments>
		<pubDate>Mon, 08 Dec 2008 12:15:38 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle性能优化]]></category>

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

		<category><![CDATA[tuning]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=60</guid>
		<description><![CDATA[故障发生时间：12月6日早上
系统环境：HP Superdome系列，128G内存，64CPU,Oracle 9.2.0.8
故障现象：CPU占用将近100%，运行队列达到60-80，应用反应速度很慢。
这是一个省级电信的核心系统。
在用户反映速度很慢后，在主机上检查发现CPU很高，将近100%，而运行队列达到了60-80。检查Oracle，发现很多的会话在等待latch free，latch#为98

SQL> select * from v$latchname where latch#=98;
&#160;&#160;&#160;&#160;LATCH#&#160;NAME
----------&#160;----------------------------------------------------------------
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;98&#160;cache&#160;buffers&#160;chains
检查正在等待latch free的会话正在执行的SQL，大部分都在执行类似于下面的SQL：
SELECT&#160;SUM(cnt),
&#160;&#160;&#160;&#160;&#160;&#160;&#160;to_char(nvl(SUM(nvl(amount,&#160;0))&#160;/&#160;100,&#160;0),&#160;&#8217;FM9999999999990.90&#8242;)&#160;amount
&#160;&#160;FROM&#160;(select&#160;count(payment_id)&#160;cnt,&#160;SUM(amount)&#160;amount
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;from&#160;payment
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;where&#160;staff_id&#160;=&#160;592965
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;and&#160;CREATED_DATE&#160;>=&#160;trunc(sysdate)
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;and&#160;state&#160;=&#160;&#8217;C0C&#8217;
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;and&#160;operation_type&#160;in&#160;(&#8217;5KA&#8217;,&#160;&#8217;5KB&#8217;,&#160;&#8217;5KC&#8217;,&#160;&#8217;5KP&#8217;))
看起来这个SQL并不复杂，查看其执行计划：

PLAN_TABLE_OUTPUT
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------
&#124;&#160;Id&#160;&#160;&#124;&#160;Operation&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;Name&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;Rows&#160;&#160;&#124;&#160;Bytes&#160;&#124;&#160;Cost&#160;&#160;&#124;&#160;Pstart&#124;&#160;Pstop&#160;&#124;
--------------------------------------------------------------------------------------------------------------------
&#124;&#160;&#160;&#160;0&#160;&#124;&#160;SELECT&#160;STATEMENT&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;1&#160;&#124;&#160;&#160;&#160;&#160;26&#160;&#124;&#160;&#160;&#160;125K&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;
&#124;&#160;&#160;&#160;1&#160;&#124;&#160;&#160;SORT&#160;AGGREGATE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;1&#160;&#124;&#160;&#160;&#160;&#160;26&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;
&#124;&#160;&#160;&#160;2&#160;&#124;&#160;&#160;&#160;VIEW&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;1&#160;&#124;&#160;&#160;&#160;&#160;26&#160;&#124;&#160;&#160;&#160;125K&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;
&#124;&#160;&#160;&#160;3&#160;&#124;&#160;&#160;&#160;&#160;SORT&#160;AGGREGATE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;1&#160;&#124;&#160;&#160;&#160;&#160;30&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;
&#124;*&#160;&#160;4&#160;&#124;&#160;&#160;&#160;&#160;&#160;TABLE&#160;ACCESS&#160;BY&#160;GLOBAL&#160;INDEX&#160;ROWID&#124;&#160;PAYMENT&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;19675&#160;&#124;&#160;&#160;&#160;576K&#124;&#160;&#160;&#160;125K&#124;&#160;ROWID&#160;&#124;&#160;ROW&#160;L&#160;&#124;
&#124;*&#160;&#160;5&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;INDEX&#160;RANGE&#160;SCAN&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;IDX_PAYMENT_CREATED_DATE8&#160;&#160;&#124;&#160;&#160;1062K&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;3919&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#124;
--------------------------------------------------------------------------------------------------------------------
Predicate&#160;Information&#160;(identified&#160;by&#160;operation&#160;id):
---------------------------------------------------
&#160;&#160;&#160;4&#160;-&#160;filter(&#8221;PAYMENT&#8221;.&#8221;STAFF_ID&#8221;=521840&#160;AND&#160;&#8221;PAYMENT&#8221;.&#8221;STATE&#8221;=&#8217;C0C&#8217;&#160;AND&#160;(&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KA&#8217;&#160;OR
&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KB&#8217;&#160;OR&#160;&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KC&#8217;&#160;OR&#160;&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KP&#8217;))
&#160;&#160;&#160;5&#160;-&#160;access(&#8221;PAYMENT&#8221;.&#8221;CREATED_DATE&#8221;>=TRUNC(SYSDATE@!))
Note:&#160;cpu&#160;costing&#160;is&#160;off

从执行计划里面可以看到，Oracle评估出，利用索引扫描返回的行数高达100万行，可想而知，这就是产生众多latch buffers chains latch争用的原因。
检查PAYMENT表的索引：
SQL> select index_name,index_type from dba_indexes where table_name=&#8217;PAYMENT&#8217; and table_owner=&#8217;ACCT&#8217;;
INDEX_NAME&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;INDEX_TYPE
------------------------------&#160;---------------------------
IDX_OPERATED_PAYMENT_SERIAL8&#160;&#160;&#160;NORMAL
IDX_PAYMENT_ACCT_ID8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
IDX_PAYMENT_CREATED_DATE8&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
IDX_PAYMENT_PAYED_METHOD8&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
IDX_PAYMENT_PAYMENT_METHOD8&#160;&#160;&#160;&#160;NORMAL
IDX_PAYMENT_SERV_ID8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
IDX_PAYMENT_STAFF_DATE8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
IDX_PAYMENT_STATE_DATE8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
PK_PAYMENT13&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;NORMAL
SQL> select index_name,column_name,column_position from dba_ind_columns where table_owner=&#8217;ACCT&#8217; and table_name=&#8217;PAYMENT&#8217; order by 1,3;
INDEX_NAME&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;COLUMN_NAME&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;COLUMN_POSITION
------------------------------&#160;------------------------------&#160;---------------
IDX_OPERATED_PAYMENT_SERIAL8&#160;&#160;&#160;OPERATED_PAYMENT_SERIAL_NBR&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_ACCT_ID8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;ACCT_ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_CREATED_DATE8&#160;&#160;&#160;&#160;&#160;&#160;CREATED_DATE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_PAYED_METHOD8&#160;&#160;&#160;&#160;&#160;&#160;PAYED_METHOD&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_PAYMENT_METHOD8&#160;&#160;&#160;&#160;PAYMENT_METHOD&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_SERV_ID8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;SERV_ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_STAFF_DATE8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;STAFF_ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1
IDX_PAYMENT_STAFF_DATE8&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;STATE_DATE&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;2
PK_PAYMENT13&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;PAYMENT_ID&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;1

可以看到执行计划中的使用的索引IDX_PAYMENT_CREATED_DATE8是在CREATED_DATE列上建立的单列索引。
这个SQL在之前却没有出现这个问题，那问题在哪里？
如果了解电信系统的人，会知道在出帐后会有一个批量销帐的动作，这导致在这个特殊的时间里，用CREATED_DATE>=TRUNCATE(SYSDATE)这个条件会从索引扫描中返回大量的行。而实际上而回表之后用其他条件过滤后的行数仅约2万行（这是评估的数据，实际的数据远远比这个少）。很显然，如果我们建立一个复合索引，那么索引扫描返回的行数将大大减少。这里STAFF_ID这个字段是与CREATED_DATE建立复合索引最好的字段。
在STAFF_ID和CREATE_DATE列上建立复合索引后，系统马上恢复正常。不过这里把STAFF_ID做为复合索引的前导列，有两个方面的考虑，一个是根据这个SQL来看，这会大大减少索引叶块的逻辑读数量；二是会减少索引叶块的热点竞争（CREATE_DATE是单向增长的字段）。至于深层次的分析，则要结合应用，必竟做为故障处理，首要的目标是解决当前的问题。
总结：
   利用合适的复合索引，能够有效地减少索引扫描返回的行数，提高性能
   熟悉应用系统的业务，可以更清楚地知道问题的根源，减少故障处理时间
]]></description>
			<content:encoded><![CDATA[<p>故障发生时间：12月6日早上<br />
系统环境：HP Superdome系列，128G内存，64CPU,Oracle 9.2.0.8<br />
故障现象：CPU占用将近100%，运行队列达到60-80，应用反应速度很慢。</p>
<p>这是一个省级电信的核心系统。</p>
<p>在用户反映速度很慢后，在主机上检查发现CPU很高，将近100%，而运行队列达到了60-80。检查Oracle，发现很多的会话在等待latch free，latch#为98</p>
<blockquote><p>
SQL> select * from v$latchname where latch#=98;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;LATCH#&nbsp;NAME<br />
----------&nbsp;----------------------------------------------------------------<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;98&nbsp;cache&nbsp;buffers&nbsp;chains</p></blockquote>
<p>检查正在等待latch free的会话正在执行的SQL，大部分都在执行类似于下面的SQL：</p>
<blockquote><p>SELECT&nbsp;SUM(cnt),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;to_char(nvl(SUM(nvl(amount,&nbsp;0))&nbsp;/&nbsp;100,&nbsp;0),&nbsp;&#8217;FM9999999999990.90&#8242;)&nbsp;amount<br />
&nbsp;&nbsp;FROM&nbsp;(select&nbsp;count(payment_id)&nbsp;cnt,&nbsp;SUM(amount)&nbsp;amount<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;from&nbsp;payment<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;where&nbsp;staff_id&nbsp;=&nbsp;592965<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;CREATED_DATE&nbsp;>=&nbsp;trunc(sysdate)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;state&nbsp;=&nbsp;&#8217;C0C&#8217;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;and&nbsp;operation_type&nbsp;in&nbsp;(&#8217;5KA&#8217;,&nbsp;&#8217;5KB&#8217;,&nbsp;&#8217;5KC&#8217;,&nbsp;&#8217;5KP&#8217;))</p></blockquote>
<p>看起来这个SQL并不复杂，查看其执行计划：<br />
<span id="more-60"></span></p>
<blockquote><p>PLAN_TABLE_OUTPUT<br />
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------</p>
<p>--------------------------------------------------------------------------------------------------------------------<br />
|&nbsp;Id&nbsp;&nbsp;|&nbsp;Operation&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;Rows&nbsp;&nbsp;|&nbsp;Bytes&nbsp;|&nbsp;Cost&nbsp;&nbsp;|&nbsp;Pstart|&nbsp;Pstop&nbsp;|<br />
--------------------------------------------------------------------------------------------------------------------<br />
|&nbsp;&nbsp;&nbsp;0&nbsp;|&nbsp;SELECT&nbsp;STATEMENT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;26&nbsp;|&nbsp;&nbsp;&nbsp;125K|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
|&nbsp;&nbsp;&nbsp;1&nbsp;|&nbsp;&nbsp;SORT&nbsp;AGGREGATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;26&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
|&nbsp;&nbsp;&nbsp;2&nbsp;|&nbsp;&nbsp;&nbsp;VIEW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;26&nbsp;|&nbsp;&nbsp;&nbsp;125K|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
|&nbsp;&nbsp;&nbsp;3&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;SORT&nbsp;AGGREGATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;30&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
|*&nbsp;&nbsp;4&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TABLE&nbsp;ACCESS&nbsp;BY&nbsp;GLOBAL&nbsp;INDEX&nbsp;ROWID|&nbsp;PAYMENT&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;19675&nbsp;|&nbsp;&nbsp;&nbsp;576K|&nbsp;&nbsp;&nbsp;125K|&nbsp;ROWID&nbsp;|&nbsp;ROW&nbsp;L&nbsp;|<br />
|*&nbsp;&nbsp;5&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INDEX&nbsp;RANGE&nbsp;SCAN&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;IDX_PAYMENT_CREATED_DATE8&nbsp;&nbsp;|&nbsp;&nbsp;1062K|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;3919&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|<br />
--------------------------------------------------------------------------------------------------------------------</p>
<p>Predicate&nbsp;Information&nbsp;(identified&nbsp;by&nbsp;operation&nbsp;id):<br />
---------------------------------------------------</p>
<p>&nbsp;&nbsp;&nbsp;4&nbsp;-&nbsp;filter(&#8221;PAYMENT&#8221;.&#8221;STAFF_ID&#8221;=521840&nbsp;AND&nbsp;&#8221;PAYMENT&#8221;.&#8221;STATE&#8221;=&#8217;C0C&#8217;&nbsp;AND&nbsp;(&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KA&#8217;&nbsp;OR<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KB&#8217;&nbsp;OR&nbsp;&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KC&#8217;&nbsp;OR&nbsp;&#8221;PAYMENT&#8221;.&#8221;OPERATION_TYPE&#8221;=&#8217;5KP&#8217;))<br />
&nbsp;&nbsp;&nbsp;5&nbsp;-&nbsp;access(&#8221;PAYMENT&#8221;.&#8221;CREATED_DATE&#8221;>=TRUNC(SYSDATE@!))</p>
<p>Note:&nbsp;cpu&nbsp;costing&nbsp;is&nbsp;off
</p></blockquote>
<p>从执行计划里面可以看到，Oracle评估出，利用索引扫描返回的行数高达100万行，可想而知，这就是产生众多latch buffers chains latch争用的原因。<br />
检查PAYMENT表的索引：</p>
<blockquote><p>SQL> select index_name,index_type from dba_indexes where table_name=&#8217;PAYMENT&#8217; and table_owner=&#8217;ACCT&#8217;;</p>
<p>INDEX_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;INDEX_TYPE<br />
------------------------------&nbsp;---------------------------<br />
IDX_OPERATED_PAYMENT_SERIAL8&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_ACCT_ID8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_CREATED_DATE8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_PAYED_METHOD8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_PAYMENT_METHOD8&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_SERV_ID8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_STAFF_DATE8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
IDX_PAYMENT_STATE_DATE8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL<br />
PK_PAYMENT13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NORMAL</p>
<p>SQL> select index_name,column_name,column_position from dba_ind_columns where table_owner=&#8217;ACCT&#8217; and table_name=&#8217;PAYMENT&#8217; order by 1,3;</p>
<p>INDEX_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COLUMN_NAME&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;COLUMN_POSITION<br />
------------------------------&nbsp;------------------------------&nbsp;---------------<br />
IDX_OPERATED_PAYMENT_SERIAL8&nbsp;&nbsp;&nbsp;OPERATED_PAYMENT_SERIAL_NBR&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_ACCT_ID8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ACCT_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_CREATED_DATE8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;CREATED_DATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_PAYED_METHOD8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PAYED_METHOD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_PAYMENT_METHOD8&nbsp;&nbsp;&nbsp;&nbsp;PAYMENT_METHOD&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_SERV_ID8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SERV_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_STAFF_DATE8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STAFF_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1<br />
IDX_PAYMENT_STAFF_DATE8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;STATE_DATE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2<br />
PK_PAYMENT13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PAYMENT_ID&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1
</p></blockquote>
<p>可以看到执行计划中的使用的索引IDX_PAYMENT_CREATED_DATE8是在CREATED_DATE列上建立的单列索引。</p>
<p>这个SQL在之前却没有出现这个问题，那问题在哪里？<br />
如果了解电信系统的人，会知道在出帐后会有一个批量销帐的动作，这导致在这个特殊的时间里，用CREATED_DATE>=TRUNCATE(SYSDATE)这个条件会从索引扫描中返回大量的行。而实际上而回表之后用其他条件过滤后的行数仅约2万行（这是评估的数据，实际的数据远远比这个少）。很显然，如果我们建立一个复合索引，那么索引扫描返回的行数将大大减少。这里STAFF_ID这个字段是与CREATED_DATE建立复合索引最好的字段。</p>
<p>在STAFF_ID和CREATE_DATE列上建立复合索引后，系统马上恢复正常。不过这里把STAFF_ID做为复合索引的前导列，有两个方面的考虑，一个是根据这个SQL来看，这会大大减少索引叶块的逻辑读数量；二是会减少索引叶块的热点竞争（CREATE_DATE是单向增长的字段）。至于深层次的分析，则要结合应用，必竟做为故障处理，首要的目标是解决当前的问题。</p>
<p><strong>总结：<br />
   利用合适的复合索引，能够有效地减少索引扫描返回的行数，提高性能<br />
   熟悉应用系统的业务，可以更清楚地知道问题的根源，减少故障处理时间</strong></p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/composite_index_overcome_performance_problem.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>TNS_ADMIN和OEM引起的血案</title>
		<link>http://www.laoxiong.net/tns_admin_and_oem_caused_accident.html</link>
		<comments>http://www.laoxiong.net/tns_admin_and_oem_caused_accident.html#comments</comments>
		<pubDate>Fri, 28 Nov 2008 14:29:12 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle备份与恢复]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=57</guid>
		<description><![CDATA[一个客户的重要生产系统，一个USER被删除了，USER下所有的对象都被删除了。还好是下班时间，也有有效的备份，数据得以完全恢复，也没有对生产造成重大影响。
引起这个事故的，除了人为因素之外，ORACLE的BUG要负一半的责任。通过操作录像（客户对系统内做系统管理的所有机器的操作都作了录像，这点非常好），我们搞清楚了数据被删除的经过。
一个开发人员，通过OEM（Oracle Enterprise Manager Console）连接到数据库上，经过他确认OEM上的那个连接字符串是正确的，然后对USER做了删除操作，但很快发现，生产库的数据被删除了。操作录像也证明那个连接字符串是正确的，那么问题出在哪里呢？
操作的那台机器（Windows系统），在系统环境变量（我的电脑=>属性=>高级=>环境变量=>系统变量）中设置了TNS_ADMIN，指向了另外的目录。现在，TNS_ADMIN指向的目录（下面简称TNS_ADMIN目录）和%ORACLE_HOME%\NETWORK\ADMIN（下面简称ORACLE目录）下都有TNSNAMES.ORA这个文件。在TNS_ADMIN中，TNSNAMES.ORA有一TNSNAME，指向生产库。在ORACLE目录中，TNSNAMES.ORA中有一同样的名称的TNSNAME指向开发库。
OEM在处理TNS_ADMIN上是有问题的。OEM在启动后，在左边的数据库目录树，是从ORACLE目录的TNSNAMES.ORA中解析出来的，完全忽略了TNS_ADMIN环境变量，就算是执行”将数据库添加到树“操作，也是完全忽略了TNS_ADMIN变量，操作的是ORACLE目录中的TNSNAMES.ORA文件，显示的连接字符串信息也是从那个文件中得到的。下面是显示信息的截图：


然而，在用这个TNSNAME进行连接数据库时，却是按照TNS_ADMIN目录中的TNSNAMES.ORA文件的配置进行连接的，如果这两个TNSNAMES.ORA都有这个TNSNAME，那么不幸就发生了，本来我们期望是连接到OEM中显示的那个数据库上，结果却连接到了另一个库上。这可以是说OEM的重大BUG。
这里谈到的OEM是9i的版本，NetCA也有这个问题，但Net Manager没有这个问题。
事情虽然过去了，但是以下几件事情我们仍然值得我们牢记：

有效的备份，特别是归档模式下的有效物理备份，是保证数据不会被丢失的前提。
数据库用户权限的管理，需要遵循”最少权限“的原则，不可忽视。很多数据库管理人员为了方便，给Oracle用户太大的权限，甚至是DBA角色权限。这是非常危险的。

有了备份仍然不够，需要做恢复测试，避免出现问题发现备份不能恢复，否则悔之晚矣。这次事故中，由于第三方的备份软件问题，导致数据恢复至少多花了三个小时的时间。要是之前有做过完整的测试，则会发现备份软件的问题。
一些危险的操作，如删除用户，删除表等操作，一定要有规范的流程，确认无误后再执行。

还有以下我的一些个人观点：

数据库管理时，尽量少用图形化的软件，一次DEL按键就能葬送整个系统。
尽量将生产系统、测试系统与开发库隔离，比如禁止在开发机器上直接连接生产库，开发完成后，需要部署到生产库时，遵循专门的流程进行。也就是要规范开发流程。

]]></description>
			<content:encoded><![CDATA[<p>一个客户的重要生产系统，一个USER被删除了，USER下所有的对象都被删除了。还好是下班时间，也有有效的备份，数据得以完全恢复，也没有对生产造成重大影响。</p>
<p>引起这个事故的，除了人为因素之外，ORACLE的BUG要负一半的责任。通过操作录像（客户对系统内做系统管理的所有机器的操作都作了录像，这点非常好），我们搞清楚了数据被删除的经过。</p>
<p>一个开发人员，通过OEM（Oracle Enterprise Manager Console）连接到数据库上，经过他确认OEM上的那个连接字符串是正确的，然后对USER做了删除操作，但很快发现，生产库的数据被删除了。操作录像也证明那个连接字符串是正确的，那么问题出在哪里呢？</p>
<p>操作的那台机器（Windows系统），在系统环境变量（我的电脑=>属性=>高级=>环境变量=>系统变量）中设置了TNS_ADMIN，指向了另外的目录。现在，TNS_ADMIN指向的目录（下面简称TNS_ADMIN目录）和%ORACLE_HOME%\NETWORK\ADMIN（下面简称ORACLE目录）下都有TNSNAMES.ORA这个文件。在TNS_ADMIN中，TNSNAMES.ORA有一TNSNAME，指向生产库。在ORACLE目录中，TNSNAMES.ORA中有一同样的名称的TNSNAME指向开发库。</p>
<p>OEM在处理TNS_ADMIN上是有问题的。OEM在启动后，在左边的数据库目录树，是从ORACLE目录的TNSNAMES.ORA中解析出来的，完全忽略了TNS_ADMIN环境变量，就算是执行”将数据库添加到树“操作，也是完全忽略了TNS_ADMIN变量，操作的是ORACLE目录中的TNSNAMES.ORA文件，显示的连接字符串信息也是从那个文件中得到的。下面是显示信息的截图：<br />
<a href='http://www.laoxiong.net/wp-content/uploads/2008/11/1.jpg'><img src="http://www.laoxiong.net/wp-content/uploads/2008/11/1.jpg" alt="" title="OEM数据库目录树" width="232" height="183" class="alignnone size-medium wp-image-58" /></a></p>
<p><a href='http://www.laoxiong.net/wp-content/uploads/2008/11/2.jpg'><img src="http://www.laoxiong.net/wp-content/uploads/2008/11/2.jpg" alt="" title="OEM中连接字符串信息" width="629" height="253" class="alignnone size-medium wp-image-59" /></a></p>
<p>然而，在用这个TNSNAME进行连接数据库时，却是按照TNS_ADMIN目录中的TNSNAMES.ORA文件的配置进行连接的，如果这两个TNSNAMES.ORA都有这个TNSNAME，那么不幸就发生了，本来我们期望是连接到OEM中显示的那个数据库上，结果却连接到了另一个库上。这可以是说OEM的重大BUG。</p>
<p>这里谈到的OEM是9i的版本，NetCA也有这个问题，但Net Manager没有这个问题。</p>
<p>事情虽然过去了，但是以下几件事情我们仍然值得我们牢记：</p>
<ul>
<li>有效的备份，特别是归档模式下的有效物理备份，是保证数据不会被丢失的前提。</li>
<li>数据库用户权限的管理，需要遵循”最少权限“的原则，不可忽视。很多数据库管理人员为了方便，给Oracle用户太大的权限，甚至是DBA角色权限。这是非常危险的。</li>
<li>
有了备份仍然不够，需要做恢复测试，避免出现问题发现备份不能恢复，否则悔之晚矣。这次事故中，由于第三方的备份软件问题，导致数据恢复至少多花了三个小时的时间。要是之前有做过完整的测试，则会发现备份软件的问题。</li>
<li>一些危险的操作，如删除用户，删除表等操作，一定要有规范的流程，确认无误后再执行。</li>
</ul>
<p>还有以下我的一些个人观点：</p>
<ul>
<li>数据库管理时，尽量少用图形化的软件，一次DEL按键就能葬送整个系统。</li>
<li>尽量将生产系统、测试系统与开发库隔离，比如禁止在开发机器上直接连接生产库，开发完成后，需要部署到生产库时，遵循专门的流程进行。也就是要规范开发流程。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/tns_admin_and_oem_caused_accident.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>绑定变量与函数调用</title>
		<link>http://www.laoxiong.net/bind_variable_and_call_function.html</link>
		<comments>http://www.laoxiong.net/bind_variable_and_call_function.html#comments</comments>
		<pubDate>Sat, 22 Nov 2008 14:53:18 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle性能优化]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=56</guid>
		<description><![CDATA[本文源起小荷博客中的文章“一次cpu的user比例过高的调优”，文章中提到的占用CPU比较高的SQL语句，消耗的CPU比逻辑读还要高的SQL还要多。这两条SQL是：
SELECT NETWORKTYPEID FROM PROBLEM_TAB WHERE PREFIXNUM = SUBSTR(:B1 , 1, 7)
select provinceid into :b0  from PROBLEM_TAB where PREFIXNUM=substr(:b1,1,7)
我关注这个的原因是，为啥这两个SQL比较消耗CPU，比逻辑读更高的SQL消耗得还多。这里让我感兴趣的是，这里使用了函数，函数的参数使用了绑定变量。那么，有一个问题，那就是这个函数会被调用多少次？1次还是与表中所有行相同的次数？我的推测是对于结果确定性（deterministic）的函数，如果传入参数有绑定变量，那么会是被引用（如值的比较）的次数，如果传入的参数是确定的值，那么应该是1次。这个推测是不是正确的呢，让我们来做一些测试。
首先创建测试用的函数：
create or replace package pkg_test is
  g_cnt number;
  function f_substr(iv_str varchar2, iv_pos in number, iv_len in number)
    return varchar2 deterministic;
end pkg_test;
create or replace package body pkg_test is
  function f_substr(iv_str varchar2, iv_pos [...]]]></description>
			<content:encoded><![CDATA[<p>本文源起<a href="http://www.oracleblog.cn">小荷博客</a>中的文章“<a href="http://www.oracleblog.cn/working-case/tuning-of-high-user-cpu/">一次cpu的user比例过高的调优</a>”，文章中提到的占用CPU比较高的SQL语句，消耗的CPU比逻辑读还要高的SQL还要多。这两条SQL是：</p>
<blockquote><p>SELECT NETWORKTYPEID FROM PROBLEM_TAB WHERE PREFIXNUM = SUBSTR(:B1 , 1, 7)<br />
select provinceid into :b0  from PROBLEM_TAB where PREFIXNUM=substr(:b1,1,7)</p></blockquote>
<p>我关注这个的原因是，为啥这两个SQL比较消耗CPU，比逻辑读更高的SQL消耗得还多。这里让我感兴趣的是，这里使用了函数，函数的参数使用了绑定变量。那么，有一个问题，那就是这个函数会被调用多少次？1次还是与表中所有行相同的次数？我的推测是对于结果确定性（deterministic）的函数，如果传入参数有绑定变量，那么会是被引用（如值的比较）的次数，如果传入的参数是确定的值，那么应该是1次。这个推测是不是正确的呢，让我们来做一些测试。</p>
<p>首先创建测试用的函数：</p>
<blockquote><p>create or replace package pkg_test is</p>
<p>  g_cnt number;</p>
<p>  function f_substr(iv_str varchar2, iv_pos in number, iv_len in number)<br />
    return varchar2 deterministic;</p>
<p>end pkg_test;</p>
<p>create or replace package body pkg_test is</p>
<p>  function f_substr(iv_str varchar2, iv_pos in number, iv_len in number)<br />
    return varchar2 deterministic is<br />
  begin<br />
    g_cnt:=g_cnt+1;<br />
    return substr(iv_str, iv_pos, iv_len);<br />
  end;<br />
end pkg_test;
</p></blockquote>
<p><span id="more-56"></span><br />
创建一个测试表：</p>
<blockquote><p>SQL> create table t1 as select * from dba_objects where rownum< =1000;</p>
<p>Table created.</p></blockquote>
<p>下面首先测试函数调用时传入的参数全部是常量时的情况：</p>
<blockquote><p>SQL> set serverout on<br />
SQL> exec pkg_test.g_cnt:=0;  </p>
<p>PL/SQL procedure successfully completed.<br />
SQL> select count(*) from t1 where object_name = pkg_test.f_substr(&#8217;T1AAADBAADFA&#8217;,1,2);</p>
<p>  COUNT(*)<br />
----------<br />
         0<br />
SQL> exec dbms_output.put_line(pkg_test.g_cnt);<br />
1</p></blockquote>
<p>可以看到f_substr函数只调用了<strong>1</strong>次。<br />
再看看函数调用时传入的参数含有绑定变量时的情况：</p>
<blockquote><p>SQL> var str varchar2(50);<br />
SQL> exec :str:=&#8217;T1AAADBAADFA&#8217;;</p>
<p>PL/SQL procedure successfully completed.<br />
SQL> exec pkg_test.g_cnt:=0;  </p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> select count(*) from t1 where object_name = pkg_test.f_substr(:str,1,2);</p>
<p>  COUNT(*)<br />
----------<br />
         0<br />
SQL> exec dbms_output.put_line(pkg_test.g_cnt);<br />
1000<br />
PL/SQL procedure successfully completed.</p></blockquote>
<p>可以看到这一次，f_substr被调用了<strong>1000</strong>次。</p>
</blockquote>
<p>不过，如果我们调用f_substr时，传入的参数第1个（类型为varchar2）为常量，而第2个和第3个参数（类型为number），重新进行上述测试，则f_substr被调用的次数始终为<strong>1</strong>次。看起来，<strong>在参数使用绑定变量时，函数被调用的次数与绑定变量的参数类型有关系</strong>。</p>
<p>如果把函数调用放在select后的字段列表（即做为选择结果），测试结果也一样。<br />
但也有例外情况，比如：</p>
<blockquote><p>select count(*) from t1 where  pkg_test.f_substr(:str,:cnt,2)=pkg_test.f_substr(:str,:cnt,2);</p></blockquote>
<p>函数就只调用了<strong>2</strong>次。不过这种情况非常少见，谁会这样写SQL啊？<br />
上面的测试都是对“确定性”的函数进行的测试，如果函数不是确定性的呢？把f_substr函数定义中的deterministic关键字去掉，再进行测试：</p>
<blockquote><p>SQL> exec pkg_test.g_cnt:=0;<br />
SQL> select count(*) from t1 where object_name=pkg_test.f_substr(&#8217;T1AAADAF&#8217;,1,2);</p>
<p>  COUNT(*)<br />
----------<br />
         0<br />
SQL>  exec dbms_output.put_line(pkg_test.g_cnt);<br />
1000</p>
<p>PL/SQL procedure successfully completed.<br />
SQL> exec pkg_test.g_cnt:=0;</p>
<p>PL/SQL procedure successfully completed.</p>
<p>SQL> select count(*) from t1 where object_name=pkg_test.f_substr(:str,1,2);</p>
<p>  COUNT(*)<br />
----------<br />
         0</p>
<p>SQL>  exec dbms_output.put_line(pkg_test.g_cnt);<br />
1000</p>
<p>PL/SQL procedure successfully completed.<br />
SQL> exec pkg_test.g_cnt:=0;</p>
<p>PL/SQL procedure successfully completed.<br />
SQL> select count(pkg_test.f_substr(&#8217;T1AAADAF&#8217;,1,2)) from t1;</p>
<p>COUNT(PKG_TEST.F_SUBSTR(&#8217;T1AAADAF&#8217;,1,2))<br />
----------------------------------------<br />
                                    1000</p>
<p>SQL> exec dbms_output.put_line(pkg_test.g_cnt);<br />
1000</p>
<p>PL/SQL procedure successfully completed.</p></blockquote>
<p>这次我们可以看到，对于不确定性的函数，即使传入的参数都是字面值(literal)常量，ORACLE也没有对其优化。在这一轮测试中，只有像</p>
<blockquote><p>select count(*) from t1 where pkg_test.f_substr(:str,1,2)=pkg_test.f_substr(:str,1,2);</p></blockquote>
<p>这样的SQL，函数仍然只调用了两次。</p>
<p>还有很多复杂的情况，没有测试。比如表连接，分析函数等。但从上面的测试中，我们还是可以得出下面的结论：</p>
<ul>
<li>
在SQL语句中，函数的调用次数，跟函数是否为确定性函数有关。只有在函数为确定性时，ORACLE才能进行函数调用次数的优化。</li>
<li>
在SQL语句中，函数的调用次数，如果向函数传入的参数是绑定变量时，调用次数跟那个参数的类型有关。有的类型如varchar2类型会导致不能对调用次数做优化。</li>
<li>
<p>因此，如果用户自定义的函数，尽量使用deterministic关键字。以便让ORACLE能够进行优化。</li>
<li>
SQL语句调用函数时，传入的参数如果有绑定变量，应考虑对函数调用次数的影响。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/bind_variable_and_call_function.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>怎样用调试工具Dump Oracle系统状态</title>
		<link>http://www.laoxiong.net/how_debugger_dump_oracle_state.html</link>
		<comments>http://www.laoxiong.net/how_debugger_dump_oracle_state.html#comments</comments>
		<pubDate>Thu, 20 Nov 2008 18:03:37 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle]]></category>

		<category><![CDATA[Oracle Internal研究]]></category>

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

		<category><![CDATA[internal]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=53</guid>
		<description><![CDATA[如果Oracle数据库hang住了，对Oracle做system dump，或做hang analyze，是研究和解决问题的有效办法，至少在提交SR时能够有更多的有用信息。如果能够连接数据库，并能够进行操作，那么用oradebug是简单快捷的办法。
但有的时候，数据库由于hang住，sqlplus不能连接时(在10g可以尝试用sqlplus -prelim连接数据库），可以使用操作系统上的调试工具来dump oracle系统状态。在记一次Oracle数据库无响应（hang住）故障的处理一文中，就曾使用dbx做systemstate dump，并发现问题所在，并最终解决了问题。下面是当时用dbx做dump的过程：
# dbx -a 446910
    Waiting to attach to process 446910 …
    Successfully attached to oracle.
    Type ‘help’ for help.
    reading symbolic information …
    stopped in iosl.select at 0×9000000000c94d8 ($t2)
    0×9000000000c94d8 (select+0xfffffffffff06318) e8410028 [...]]]></description>
			<content:encoded><![CDATA[<p>如果Oracle数据库hang住了，对Oracle做system dump，或做hang analyze，是研究和解决问题的有效办法，至少在提交SR时能够有更多的有用信息。如果能够连接数据库，并能够进行操作，那么用oradebug是简单快捷的办法。</p>
<p>但有的时候，数据库由于hang住，sqlplus不能连接时(在10g可以尝试用sqlplus -prelim连接数据库），可以使用操作系统上的调试工具来dump oracle系统状态。在<a href="http://www.laoxiong.net/oracle_hang.html">记一次Oracle数据库无响应（hang住）故障的处理</a>一文中，就曾使用dbx做systemstate dump，并发现问题所在，并最终解决了问题。下面是当时用dbx做dump的过程：</p>
<blockquote><p># dbx -a 446910<br />
    Waiting to attach to process 446910 …<br />
    Successfully attached to oracle.<br />
    Type ‘help’ for help.<br />
    reading symbolic information …<br />
    stopped in iosl.select at 0×9000000000c94d8 ($t2)<br />
    0×9000000000c94d8 (select+0xfffffffffff06318) e8410028 ld r2,0×28(r1)<br />
    (dbx) print ksudss(10)</p>
<p>    Segmentation fault in slrac at 0×100083aa0 ($t2)<br />
    0×100083aa0 (slrac+0xe4) 88030000 lbz r0,0×0(r3)<br />
    (dbx) detach</p></blockquote>
<p>从上面可以看到，使用dbx做dump的过程为：</p>
<ul>
<li>
找到有异常的进程号，比如CPU非常高，HANG住的进程等。如果做系统范围的systemstate dump，可以是其他的进程。</li>
<li>dbx -a < 进程号></li>
<li>print ksudss(10)  --这里是直接调用ORACLE程序中的ksudss函数，dump level为10，就等同于在sqlplus 中用oradebug dump systemstate 10</li>
<li>detach</li>
<li>quit</li>
</ul>
<p>在LINUX下可以使用gdb，下面是一个例子：</p>
<blockquote><p>[oracle@xty ~]$ ps -ef | grep LOCAL<br />
oracle    3765  3764  1 05:55 ?        00:00:00 oraclexty (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))<br />
oracle    3767  3668  0 05:55 pts/2    00:00:00 grep LOCAL<br />
[oracle@xty ~]$ gdb $ORACLE_HOME/bin/oracle 3765<br />
GNU gdb Red Hat Linux (6.1post-1.20040607.62rh)<br />
Copyright 2004 Free Software Foundation, Inc.<br />
GDB is free software, covered by the GNU General Public License, and you are<br />
welcome to change it and/or distribute copies of it under certain conditions.<br />
Type &#8220;show copying&#8221; to see the conditions.<br />
There is absolutely no warranty for GDB.  Type &#8220;show warranty&#8221; for details.<br />
This GDB was configured as &#8220;i386-redhat-linux-gnu&#8221;&#8230;(no debugging symbols found)&#8230;Using host libthread_db library &#8220;/lib/tls/libthread_db.so.1&#8243;.</p>
<p>Attaching to program: /u01/app/oracle/product/10.1.0/db_1/bin/oracle, process 3765<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libskgxp10.so&#8230;(no debugging symbols found)&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libskgxp10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libhasgen10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libhasgen10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libskgxn2.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libskgxn2.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libocr10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libocr10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libocrb10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libocrb10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libocrutl10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libocrutl10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libjox10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libjox10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libclsra10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libclsra10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libdbcfg10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libdbcfg10.so<br />
Reading symbols from /u01/app/oracle/product/10.1.0/db_1/lib/libnnz10.so&#8230;done.<br />
Loaded symbols for /u01/app/oracle/product/10.1.0/db_1/lib/libnnz10.so<br />
Reading symbols from /usr/lib/libaio.so.1&#8230;done.<br />
Loaded symbols for /usr/lib/libaio.so.1<br />
Reading symbols from /lib/libdl.so.2&#8230;done.<br />
Loaded symbols for /lib/libdl.so.2<br />
Reading symbols from /lib/tls/libm.so.6&#8230;done.<br />
Loaded symbols for /lib/tls/libm.so.6<br />
Reading symbols from /lib/tls/libpthread.so.0&#8230;done.<br />
[Thread debugging using libthread_db enabled]<br />
[New Thread -1219938624 (LWP 3765)]<br />
Loaded symbols for /lib/tls/libpthread.so.0<br />
Reading symbols from /lib/libnsl.so.1&#8230;done.<br />
Loaded symbols for /lib/libnsl.so.1<br />
Reading symbols from /lib/tls/libc.so.6&#8230;done.<br />
Loaded symbols for /lib/tls/libc.so.6<br />
Reading symbols from /lib/ld-linux.so.2&#8230;done.<br />
Loaded symbols for /lib/ld-linux.so.2<br />
Reading symbols from /lib/libnss_files.so.2&#8230;done.<br />
Loaded symbols for /lib/libnss_files.so.2<br />
0&#215;006967a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2<br />
(gdb) print ksudss(10)<br />
[Switching to Thread -1219938624 (LWP 3765)]<br />
$1 = 213658428<br />
(gdb) detach<br />
Detaching from program: /u01/app/oracle/product/10.1.0/db_1/bin/oracle, process 3765<br />
(gdb) quit</p></blockquote>
<p>然后我们可以找到有dump结果的trace文件：<br />
<span id="more-53"></span></p>
<blockquote><p>[oracle@xty ~]$ cd $ORACLE_BASE/admin/xty/udump<br />
[oracle@xty udump]$ ls -lrt | grep 3765<br />
-rw-r-----  1 oracle oinstall 599705 Nov 21 05:56 xty_ora_3765.trc</p></blockquote>
<p>根据debugger工具attach进程的不同，trace文件一般在user_dump_dest或background_dump_dest目录下。</p>
<p>在LINUX下用gdb，在AIX下用dbx，那么在HP-UX下呢，可以用HP的wdb（可以到<a href="http://h21007.www2.hp.com/portal/site/dspp/menuitem.863c3e4cbcdc3f3515b49c108973a801?ciid=29080f1bace021100f1bace02110275d6e10RCRD">HP WDB</a>查看HP WDB的详细信息和下载最新的版本。在solaris上，也会有dbx或gdb（各个平台有多种不同的debugger，其他还有adb,mdb等等）。有兴趣的朋友可以用用。</p>
<p>除了上面提到的systemstate dump，还能不能够做其他的dump？答案是肯定的，以下是一些dump相关的函数：</p>
<blockquote><p>print ksdhng(3,1,0)  相当于oradebug hanganalyze 3<br />
print ksudps(10)  相当于oradebug dump processstate 10<br />
print curdmp()   相当于oradebug call curdmp（也就是oradebug dump cursordump)<br />
print ksdtrc(4)   相当于oradebug dump events 4（这里参数表示level,1--session,2--process,4--system)
</p></blockquote>
<p>以上列出的，不一定对处理HANG有意义，只是这里觉得有些意思。^_^.其他还有意思的包括：</p>
<blockquote><p>print ksdsel(10046,12)  --相当于为attach的进程设置10046事件level 12<br />
print skdxipc()  --相当于oradebug ipc<br />
print skdxprst() --相当于oradebug procstat
</p></blockquote>
<p><strong>注意：不要在正常运行的生产系统上运行和测试。</strong></p>
<p>当然，如果能用oradebug，那么就用oradebug，毕竟方便很多，也更安全。这里只是对使用debugger做dump一些扩充，供有兴趣研究的朋友参考。</p>
<p>补充：在HP-UX上使用gdb进行system dump，可能会更复杂，可以参考Oracle Metalink Doc 273324.1</p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/how_debugger_dump_oracle_state.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>inside sqlplus prelim</title>
		<link>http://www.laoxiong.net/inside_sqlplus_prelim.html</link>
		<comments>http://www.laoxiong.net/inside_sqlplus_prelim.html#comments</comments>
		<pubDate>Sat, 15 Nov 2008 08:10:36 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle Internal研究]]></category>

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

		<category><![CDATA[sqlplus]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=55</guid>
		<description><![CDATA[我们知道，在Oracle 10g中，如果数据库实例hang住了，应用及sqlplus都不能连接时，可以用sqlplus -prelim连接数据库。那么sqlplus连接时，加上-prelim这个参数有什么特别的地方呢？下面，让我们来研究一下：
测试环境：Linux AS4上的Oracle 10.2.0.1，客户端(sqlplus)版本为Windows 2003下的10.2.0.1。
首先在数据库上启用10046事件：
SQL> alter system set events &#8216;10046 trace name context forever&#8217;;
System altered.

先用普通的方式连接：
D:\>sqlplus /nolog
SQL*Plus: Release 10.2.0.1.0 - Production on 星期六 11月 15 15:36:02 2008
Copyright (c) 1982, 2005, Oracle.  All rights reserved.
SQL> conn sys/manage@xty as sysdba
已连接。
SQL> exit
从 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining [...]]]></description>
			<content:encoded><![CDATA[<p>我们知道，在Oracle 10g中，如果数据库实例hang住了，应用及sqlplus都不能连接时，可以用sqlplus -prelim连接数据库。那么sqlplus连接时，加上-prelim这个参数有什么特别的地方呢？下面，让我们来研究一下：</p>
<p>测试环境：Linux AS4上的Oracle 10.2.0.1，客户端(sqlplus)版本为Windows 2003下的10.2.0.1。</p>
<p>首先在数据库上启用10046事件：</p>
<blockquote><p>SQL> alter system set events &#8216;10046 trace name context forever&#8217;;</p>
<p>System altered.
</p></blockquote>
<p>先用普通的方式连接：</p>
<blockquote><p>D:\>sqlplus /nolog</p>
<p>SQL*Plus: Release 10.2.0.1.0 - Production on 星期六 11月 15 15:36:02 2008</p>
<p>Copyright (c) 1982, 2005, Oracle.  All rights reserved.</p>
<p>SQL> conn sys/manage@xty as sysdba<br />
已连接。<br />
SQL> exit<br />
从 Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production<br />
With the Partitioning, OLAP and Data Mining options 断开</p></blockquote>
<p>再看看加prelim参数时的情况：</p>
<blockquote><p>D:\>sqlplus -prelim /nolog</p>
<p>SQL*Plus: Release 10.2.0.1.0 - Production on 星期六 11月 15 15:36:34 2008</p>
<p>Copyright (c) 1982, 2005, Oracle.  All rights reserved.</p>
<p>SQL> conn sys/manage@xty as sysdba<br />
初级连接已建立<br />
SQL> exit<br />
从 ORACLE 断开</p></blockquote>
<p>从上面的信息可以看到，在使用prelim连接时，提示为“初级连接已建立”，退出sqlplus没有显示banner。<br />
也可以通过下面的方式来用prelim方式连接数据库：</p>
<blockquote><p>[oracle@xty ~]$ sqlplus /nolog</p>
<p>SQL*Plus: Release 10.2.0.3.0 - Production on Tue Dec 2 07:04:28 2008</p>
<p>Copyright (c) 1982, 2006, Oracle.  All Rights Reserved.</p>
<p>SQL> set _prelim on<br />
SQL> connect / as sysdba<br />
Prelim connection established
</p></blockquote>
<p>再看看数据库的10046 trace：</p>
<p>从生成的trace文件中，可以发现在正常连接时，连接上数据库后，sqlplus自动执行了下面的SQL：</p>
<blockquote><p>ALTER SESSION SET NLS_LANGUAGE= &#8216;SIMPLIFIED CHINESE&#8217; NLS_TERRITORY= &#8216;CHINA&#8217; NLS_CURRENCY= &#8216;￥&#8217; NLS_ISO_CURRENCY= &#8216;CHINA&#8217; NLS_NUMERIC_CHARACTERS= &#8216;.,&#8217; NLS_CALENDAR= &#8216;GREGORIAN&#8217; NLS_DATE_FORMAT= &#8216;DD-MON-RR&#8217; NLS_DATE_LANGUAGE= &#8216;SIMPLIFIED CHINESE&#8217; NLS_SORT= &#8216;BINARY&#8217; TIME_ZONE= &#8216;+08:00&#8242; NLS_COMP= &#8216;BINARY&#8217; NLS_DUAL_CURRENCY= &#8216;￥&#8217; NLS_TIME_FORMAT= &#8216;HH.MI.SSXFF AM&#8217; NLS_TIMESTAMP_FORMAT= &#8216;DD-MON-RR HH.MI.SSXFF AM&#8217; NLS_TIME_TZ_FORMAT= &#8216;HH.MI.SSXFF AM TZR&#8217; NLS_TIMESTAMP_TZ_FORMAT= &#8216;DD-MON-RR HH.MI.SSXFF AM TZR&#8217;</p>
<p>select value$ from props$ where name = &#8216;GLOBAL_DB_NAME&#8217;</p>
<p>select SYS_CONTEXT(&#8217;USERENV&#8217;, &#8216;SERVER_HOST&#8217;), SYS_CONTEXT(&#8217;USERENV&#8217;, &#8216;DB_UNIQUE_NAME&#8217;), SYS_CONTEXT(&#8217;USERENV&#8217;, &#8216;INSTANCE_NAME&#8217;), SYS_CONTEXT(&#8217;USERENV&#8217;, &#8216;SERVICE_NAME&#8217;), INSTANCE_NUMBER, STARTUP_TIME, SYS_CONTEXT(&#8217;USERENV&#8217;, &#8216;DB_DOMAIN&#8217;) from v$instance where INSTANCE_NAME=SYS_CONTEXT(&#8217;USERENV&#8217;, &#8216;INSTANCE_NAME&#8217;)</p>
<p>select decode(failover_method, NULL, 0 , &#8216;BASIC&#8217;, 1, &#8216;PRECONNECT&#8217;, 2 , &#8216;PREPARSE&#8217;, 4 , 0), decode(failover_type, NULL, 1 , &#8216;NONE&#8217;, 1 , &#8216;SESSION&#8217;, 2, &#8216;SELECT&#8217;,  4, 1), failover_retries, failover_delay, flags from service$ where name = :1</p>
</blockquote>
<p>而sqlplus使用prelim连接上数据库后，没有生成10046 trace文件，看起来没有执行SQL，也就是没有执行任何初始化动作和查询必要的信息。也许这也就是称之为“初级连接”的来历吧。</p>
<p>由于使用prelim方式连接，没有执行sql语句的，所以在数据库的某些hang住的情况下，能够连接上数据库。比如由于library cache latch 被长时间持有不能释放，不能解析SQL语句引起的hang。有的人会说，我的应用刚连上去还没做任何操作就hang住了。这只是表面现象，连接上数据库后，一般都会做一些初始化的操作，如设定环境之类的。</p>
<p>sqlplus -prelim能够在数据库hang住的情况下连接数据库，但只能说是连接，并不代表能够做很多操作。比如执行SQL查询。这种情况下，可能最有用的就是使用oradebug。</p>
<p>本文只是简单地“inside”，其实并不很深入，Oracle还会有其他的跟prelim有关的东西，是我们还没发现的。有兴趣的朋友，可以进一步研究。比如通过抓取tns包进行分析等等。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/inside_sqlplus_prelim.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>儿子两岁了</title>
		<link>http://www.laoxiong.net/son_two_years_old.html</link>
		<comments>http://www.laoxiong.net/son_two_years_old.html#comments</comments>
		<pubDate>Thu, 13 Nov 2008 13:22:03 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[My Life]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=54</guid>
		<description><![CDATA[明天，儿子就两岁了。
儿子很很喜欢飞机，天上有飞机飞过，总要抬头看看，直到看不见为止。经常缠着我们在网上找飞机图片给他看。现在至少是能分辨客机和直升机了，不过他更喜欢直升机。
儿子很喜欢建筑相关的东西，喜欢看修房子，喜欢混凝土车，喜欢挖掘车。不知道他为什么会有这种奇特的喜好？似乎小孩对什么东西都是很新奇的。
儿子常常说的话是，“爸爸是老帅哥，超超是小帅哥”
儿子常常让他妈妈做的事情是，“画鱼摆摆吹泡泡”
儿子最喜欢的电视节目是每晚19点CCTV3的“动物世界”
在儿子两岁之即，特记之。
]]></description>
			<content:encoded><![CDATA[<p>明天，儿子就两岁了。</p>
<p>儿子很很喜欢飞机，天上有飞机飞过，总要抬头看看，直到看不见为止。经常缠着我们在网上找飞机图片给他看。现在至少是能分辨客机和直升机了，不过他更喜欢直升机。</p>
<p>儿子很喜欢建筑相关的东西，喜欢看修房子，喜欢混凝土车，喜欢挖掘车。不知道他为什么会有这种奇特的喜好？似乎小孩对什么东西都是很新奇的。</p>
<p>儿子常常说的话是，“爸爸是老帅哥，超超是小帅哥”</p>
<p>儿子常常让他妈妈做的事情是，“画鱼摆摆吹泡泡”</p>
<p>儿子最喜欢的电视节目是每晚19点CCTV3的“动物世界”</p>
<p>在儿子两岁之即，特记之。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.laoxiong.net/son_two_years_old.html/feed</wfw:commentRss>
		</item>
		<item>
		<title>db_block_checking和db_block_checksum III</title>
		<link>http://www.laoxiong.net/httpwwwlaoxiongnetdb_block_checking_and_db_block_checksum_part3.html</link>
		<comments>http://www.laoxiong.net/httpwwwlaoxiongnetdb_block_checking_and_db_block_checksum_part3.html#comments</comments>
		<pubDate>Thu, 06 Nov 2008 06:16:05 +0000</pubDate>
		<dc:creator>老熊</dc:creator>
		
		<category><![CDATA[Oracle数据库管理]]></category>

		<guid isPermaLink="false">http://www.laoxiong.net/?p=52</guid>
		<description><![CDATA[前面两篇文章简要介绍了db_block_checking和db_block_checksum参数，并提到这两个参数对性能的影响。下面做个测试：
首先建一个测试表，并设置db_block_checking和db_block_checksum为false：
SQL> create table t2 (a int) tablespace test;
表已创建。
SQL> alter system set db_block_checking=false;
系统已更改。
SQL> alter system set db_block_checksum=false;
向测试表T2中四次分别插入100，000行数据：
SQL> begin
  2   for i in 1..100000 loop
  3    insert into t2 values(i);
  4  end loop;
  5  end;
  6  /
PL/SQL 过程已成功完成。
已用时间:  00: 00: 06.02
SQL> commit;
提交完成。
已用时间:  [...]]]></description>
			<content:encoded><![CDATA[<p>前面两篇文章简要介绍了db_block_checking和db_block_checksum参数，并提到这两个参数对性能的影响。下面做个测试：</p>
<p>首先建一个测试表，并设置db_block_checking和db_block_checksum为false：</p>
<blockquote><p>SQL> create table t2 (a int) tablespace test;</p>
<p>表已创建。<br />
SQL> alter system set db_block_checking=false;</p>
<p>系统已更改。</p>
<p>SQL> alter system set db_block_checksum=false;</p></blockquote>
<p>向测试表T2中四次分别插入100，000行数据：</p>
<blockquote><p>SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 06.02<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.02<br />
SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 05.04<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.02<br />
SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。<br />
<span id="more-52"></span><br />
已用时间:  00: 00: 07.04<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.01<br />
SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 07.04<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.01</p></blockquote>
<p>四次数据插入中，最长的时间为7.04秒，最短时间为5.05秒，平均6.29秒。</p>
<p>下面再看看将这两个参数设置为true的测试结果：</p>
<blockquote><p>SQL> alter system set db_block_checking=true;</p>
<p>系统已更改。</p>
<p>SQL> alter system set db_block_checksum=true;</p>
<p>系统已更改。</p>
<p>SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 11.02<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.02<br />
SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 12.01<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.02<br />
SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 09.00<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.04<br />
SQL> begin<br />
  2   for i in 1..100000 loop<br />
  3    insert into t2 values(i);<br />
  4  end loop;<br />
  5  end;<br />
  6  /</p>
<p>PL/SQL 过程已成功完成。</p>
<p>已用时间:  00: 00: 11.04<br />
SQL> commit;</p>
<p>提交完成。</p>
<p>已用时间:  00: 00: 00.00<br />
SQL> alter system checkpoint;</p>
<p>系统已更改。</p>
<p>已用时间:  00: 00: 01.02</p></blockquote>
<p>在上面的测试中，四次数据插入，最长的时间为12.01秒，最短时间为9.00秒，平均为10.77秒。</p>
<p>可以看出，这两者的差别是相当显著的，这两者参数设置为false时比设置为true竟然快了40%以上。不过这只是个简单的测试，实际情况可能没那么突出，但差异在10%以上是有可能的。</p>
<p><strong>值得注意的是，性能上的差异，主要是由于CPU的消耗造成的，对于CPU资源不足的系统，将这两个参数设置为TRUE无疑会增大CPU的负担，引起性能问题。</strong>同时还会引起<strong>redo copy latch</strong>的持有时间增加和引起这个latch的竞争。</p>
<p>另外，由于不管db_block_checking和db_block_checksum这两个参数的值为何值，SYSTEM表空间都会进行做checking和checksum，除非把隐含参数<strong>_db_always_check_system_ts</strong>设置为FALSE，当然为了SYSTEM表空间数据安全，不建议将这个隐含参数值设置为FALSE。<strong>因此，不要将用户表和索引放到SYSTEM空间中。</strong></p>
<p>在启用一起特定的功能后，SYSTEM表空间中一些表和索引会增长很快。比如启用了审计并且将审计日志存储到数据库中，则AUD$和FGA_LOG$会迅速增长；如果使用高级复制，DEF$_AQCALL表会增加很快，并且如果要复制的数据量比较大，则这个表上的DML是非常多的，在这样的情况会下，会消耗更多的CPU和引起性能降低。如果使用了审计和高级复制，建议将AUD$