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

<channel>
	<title>OS与Oracle &#187; Hash Join</title>
	<atom:link href="http://www.os2ora.com/tag/hash-join/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.os2ora.com</link>
	<description>专注于现实世界Oracle数据库的高性能，高可扩展性与新一代数据库Exadata架构</description>
	<lastBuildDate>Mon, 19 Sep 2011 09:10:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>利用SQL Monitor Report对SQL进行诊断与调优</title>
		<link>http://www.os2ora.com/use-sql-monitor-report-to-tune-and-diagnose-sql/</link>
		<comments>http://www.os2ora.com/use-sql-monitor-report-to-tune-and-diagnose-sql/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 13:38:51 +0000</pubDate>
		<dc:creator>Kaya</dc:creator>
				<category><![CDATA[Exadata]]></category>
		<category><![CDATA[Oracle管理与维护]]></category>
		<category><![CDATA[数据库性能调优]]></category>
		<category><![CDATA[Hash Join]]></category>
		<category><![CDATA[Hash Join Buffered]]></category>
		<category><![CDATA[SQL Monitor Report]]></category>
		<category><![CDATA[Tunning]]></category>
		<category><![CDATA[诊断]]></category>

		<guid isPermaLink="false">http://www.os2ora.com/use-sql-monitor-report-to-tune-and-diagnose-sql/</guid>
		<description><![CDATA[本文要分析的是下面这个SQL，执行了半个多钟头还没返回结果。
Wait events 是了解Oracle运行状态的一个重要途径。对于某个具体的SQL，SQL Monitor Report提供了drill down的方式得到这个具体SQL在运行中的wait events的分布情况，下面是SQL Monitor Report的相应图形。
这里最突出的等待事件是enq: TS - contention，这是关于临时segment的等待事件，这可能是一般的表空间的争用(例如并行直接路径加载数据)，也可能是临时表空间的争用(例如为了hash join或者sort)。那么这时临时表空间的增长状态是怎么样子的呢？SQL Monitor Report提供了这方面的信息......]]></description>
			<content:encoded><![CDATA[<p>Kaya 发表于 <a href="http://www.os2ora.com/">os2ora.com</a>&#160;</p>
<p>本文要分析的是下面这个SQL，执行了半个多钟头还没返回结果。</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #808080; font-style: italic;">/*+ APPEND */</span>
<span style="color: #993333; font-weight: bold;">INTO</span>
 T_D
<span style="color: #993333; font-weight: bold;">SELECT</span>
 <span style="color: #66cc66;">*</span>
<span style="color: #993333; font-weight: bold;">FROM</span>
 T_A a
<span style="color: #66cc66;">,</span>T_B b
<span style="color: #66cc66;">,</span>T_C c
<span style="color: #993333; font-weight: bold;">WHERE</span> a<span style="color: #66cc66;">.</span>id <span style="color: #66cc66;">=</span> b<span style="color: #66cc66;">.</span>id
<span style="color: #993333; font-weight: bold;">AND</span>   b<span style="color: #66cc66;">.</span>number <span style="color: #66cc66;">=</span> c<span style="color: #66cc66;">.</span>number
;</pre></div></div>

<p>&#160;</p>
<p>Wait events 是了解Oracle运行状态的一个重要途径。对于某个具体的SQL，SQL Monitor Report提供了drill down的方式得到这个具体SQL在运行中的wait events的分布情况，下面是SQL Monitor Report的相应图形。</p>
<p><a href="http://www.os2ora.com/wp-content/uploads/2010/01/image8.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="216" alt="image" src="http://www.os2ora.com/wp-content/uploads/2010/01/image_thumb8.png" width="814" border="0" /></a> </p>
<p>这里最突出的等待事件是enq: TS &#8211; contention，这是关于临时segment的等待事件，这可能是一般的表空间的争用(例如并行直接路径加载数据)，也可能是临时表空间的争用(例如为了hash join或者sort)。那么这时临时表空间的增长状态是怎么样子的呢？SQL Monitor Report提供了这方面的信息。</p>
<p><a href="http://www.os2ora.com/wp-content/uploads/2010/01/image9.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="156" alt="image" src="http://www.os2ora.com/wp-content/uploads/2010/01/image_thumb9.png" width="804" border="0" /></a> </p>
<p>可以看出，temp space从开始的3G慢慢增长到20G，整个过程2800 seconds，如果算下速度的话17GB/2800=6MB/s。这刚好与上面的等待事件 enq: TS &#8211; contention相吻合。</p>
<p>这是一个直接加载数据的例子，在这个例子中，最后表的大小是30GB左右。可以怀疑，这些临时表空间的分配是为了存放最后放入目标表的数据。</p>
<p>这于这个等待事件enq: TS &#8211; contention发生在这个SQL执行过程中的哪一步呢？SQL Monitor Report也给出了答案，在执行计划那一页：</p>
</p>
<p><a href="http://www.os2ora.com/wp-content/uploads/2010/01/image10.png"><img title="image" style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" height="323" alt="image" src="http://www.os2ora.com/wp-content/uploads/2010/01/image_thumb10.png" width="804" border="0" /></a> </p>
</p>
<p>注意上图鼠标位置，标志着位于HASH JOIN BUFFERED这个步骤的等待事件enq: TS – contention占了这个SQL所有等待活动的97%！</p>
<p>问题到这里已经基本明了了：</p>
<p>1. 优化器采用Hash Join Buffered的方式返回三个表Join的结果，当为这些结果集分配临时表的空间时，碰到了严重的竞争。</p>
<p>2. 由于分配速度极其缓慢，导致了整个SQL超过97%的时间花在了这个等待事件上，通过去掉这个等待事件，这个SQL应该能提升上百倍的速度。</p>
<p>解决这个问题的根本在于加速临时表空间的回收速度，不过，也有workaround的办法，那就是预先分配足够的临时表空间，避免回收临时表空间时出现TS &#8211; contention竞争。</p>
<p>另外一种思路，则在于减少对临时表空间的利用，在这里，为什么要用到这么多临时表空间在于Oracle采用Hash Join Buffered而不是采用Hash Join，这意味着Oracle会先对Join的结果集进行buffer，等到所有结果ready之后再写到目标表，另一种思路当然是让结果直接写到目标表中，也就是实现并行的DML插入操作。方法很简单：在运行这个SQL之前加上</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">ALTER</span> session enable parallel dml;</pre></div></div>

<p>即可，在这种情形下，Oracle不需要再为结果集分配临时表空间，同时，由于采用并于DML操作，整个SQL的运行时间会得到很大的提速。下面是相应的执行计划。</p>
<p><a href="http://www.os2ora.com/wp-content/uploads/2010/01/image11.png"><img title="image" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="323" alt="image" src="http://www.os2ora.com/wp-content/uploads/2010/01/image_thumb11.png" width="804" border="0" /></a> </p>
<p>可以看出，Hash Join Buffered变成了Hash Join，同时，等待事件enq: TS contention已然消失，换成了”喜闻乐见”的ON CPU。同时，整个SQL在小于30s的时间内完成了。</p>
<p>不可否认，Hash Join Buffered是这里极其隐蔽，可能不小心就被忽略了，以为上面两个执行计划就是LOAD AS SELECT的位置从第2行搬到了第4行，其实背后发生的事情远没有这么简单。以后有机会再对这个话题进行展开吧。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.os2ora.com/use-sql-monitor-report-to-tune-and-diagnose-sql/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

