<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href='http://feed.dbadoc.com/styles/feedsky8.xsl' type='text/xsl' ?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link href="http://feed.dbadoc.com" type="application/rss+xml" rel="self"></atom:link><fs:self_link href="http://feed.feedsky.com/dbadoc" type="application/rss+xml"></fs:self_link><lastBuildDate>Thu, 25 Feb 2010 02:44:30 GMT</lastBuildDate><title>dbadoc</title><description>dbadoc</description><link atom:type="text/html">http://www.dbadoc.com</link><generator xmlns="http://www.w3.org/2005/Atom" uri="http://wordpress.org/" version="2.9.2">WordPress</generator><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/feed/atom</id><link xmlns="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://www.dbadoc.com/feed/atom"></link><pubDate>Thu, 25 Feb 2010 02:44:30 GMT</pubDate><item><title>乱七八糟</title><link atom:type="text/html">http://www.dbadoc.com/2010/02/luanqibazao</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2048</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/02/luanqibazao">&lt;p&gt;12月份以后变的很消极，不想工作，不想学习，有时间只是玩游戏，玩游戏还是玩游戏。浪费了太多太多的时间，本命年的自己很傻，为此自己也受了很多伤，颓废是年末的主题语，博客也懒得写了，再加上过年放假，春节回来找房子，搬家，很多事，人也很浮躁，幸好这一切都过去了，从3月一号开始就搬到了新家，很温馨，很好的房子，心里那些乱七八糟的事也放一下了，我要开始新的生活，专心好好工作，好好拍照片，好好游泳，锻炼身体，好好生活，因为我还有我的两年计划呢，仔细想想，自己的将来也还是有盼头的，呵呵，塞翁失马焉知非福啊。&lt;/p&gt;
&lt;p&gt;3月份之后，这个博客要不要继续存在下去我现在还没有决定，如果我决定关闭它的话，文章会暂时转到wobusu.com，毕竟那里还有一段时间域名才到期。也许那个域名到期之后我就会放弃我的独立博客之旅，自己建立自己的独立博客真的花很多心血和时间，而对于我来说，似乎没有太大必要，当初建立也只是有自己一些小小的虚荣心的。不过在这个过程中也学到了很多知识，不仅仅是技术的，还有别的。而现在我的虚荣心得到满足了，也许我会放更多的时间和精力在好好生活上，有人说过：男人确实不可信，这句话是错的。男人做好自己的事业，对自己的家庭和爱人真心好，有上进心，这种男人是可信的。我愿意朝这个目标去努力。人不能太现实了，也不能太眼高手低了，也不可因为一些甜言蜜语而迷失了自己的方向，放纵自己，只知道玩，然后把自己的前途和幸福寄托在自己都不敢相信的男人身上，那样将来后悔的始终是自己，自己还是要珍惜时间，珍惜手里的幸福的，用心去经营，用心去爱，谁也不欠谁，对别人好点，对自己爱的人好点，如果不喜欢别人，或者没有想好，没有做好准备，没有下定决心，不要轻易接受别人的真心，不要轻易给别人希望，因为有些人很傻，他会当真的，当你将来让别人的希望破灭的时候，你就伤害了一颗无辜的心。&lt;/p&gt;
&lt;p&gt;过去的都淡了，将来的才幸福。自己的路自己努力吧。&lt;/p&gt;</content><thr:total>0</thr:total><description>12月份以后变的很消极，不想工作，不想学习，有时间只是玩游戏，玩游戏还是玩游戏。浪费了太多太多的时间，本命年的自己很傻，为此自己也受了很多伤，颓废是年末的主题语，博客也懒得写了，再加上过年放假，春节回来找房子，搬家，很多事，人也很浮躁，幸好这一切都过去了，从3月一号开始就搬到了新家，很温馨，很好的房[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/02/luanqibazao'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794218/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/02/luanqibazao&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794218/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794218/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;12月份以后变的很消极，不想工作，不想学习，有时间只是玩游戏，玩游戏还是玩游戏。浪费了太多太多的时间，本命年的自己很傻，为此自己也受了很多伤，颓废是年末的主题语，博客也懒得写了，再加上过年放假，春节回来找房子，搬家，很多事，人也很浮躁，幸好这一切都过去了，从3月一号开始就搬到了新家，很温馨，很好的房子，心里那些乱七八糟的事也放一下了，我要开始新的生活，专心好好工作，好好拍照片，好好游泳，锻炼身体，好好生活，因为我还有我的两年计划呢，仔细想想，自己的将来也还是有盼头的，呵呵，塞翁失马焉知非福啊。&lt;/p&gt;
&lt;p&gt;3月份之后，这个博客要不要继续存在下去我现在还没有决定，如果我决定关闭它的话，文章会暂时转到wobusu.com，毕竟那里还有一段时间域名才到期。也许那个域名到期之后我就会放弃我的独立博客之旅，自己建立自己的独立博客真的花很多心血和时间，而对于我来说，似乎没有太大必要，当初建立也只是有自己一些小小的虚荣心的。不过在这个过程中也学到了很多知识，不仅仅是技术的，还有别的。而现在我的虚荣心得到满足了，也许我会放更多的时间和精力在好好生活上，有人说过：男人确实不可信，这句话是错的。男人做好自己的事业，对自己的家庭和爱人真心好，有上进心，这种男人是可信的。我愿意朝这个目标去努力。人不能太现实了，也不能太眼高手低了，也不可因为一些甜言蜜语而迷失了自己的方向，放纵自己，只知道玩，然后把自己的前途和幸福寄托在自己都不敢相信的男人身上，那样将来后悔的始终是自己，自己还是要珍惜时间，珍惜手里的幸福的，用心去经营，用心去爱，谁也不欠谁，对别人好点，对自己爱的人好点，如果不喜欢别人，或者没有想好，没有做好准备，没有下定决心，不要轻易接受别人的真心，不要轻易给别人希望，因为有些人很傻，他会当真的，当你将来让别人的希望破灭的时候，你就伤害了一颗无辜的心。&lt;/p&gt;
&lt;p&gt;过去的都淡了，将来的才幸福。自己的路自己努力吧。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794218/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/02/luanqibazao&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794218/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794218/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">心的声音</category><pubDate>Thu, 25 Feb 2010 10:44:30 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2048</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/02/luanqibazao</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794218/5445352</fs:itemid></item><item><title>Hint</title><link atom:type="text/html">http://www.dbadoc.com/2010/02/hint</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2045</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/02/hint">&lt;p&gt;原帖见：&lt;a href=&quot;http://www.itpub.net/viewthread.php?tid=1265917&amp;amp;extra=&amp;amp;page=1&quot; target=&quot;_blank&quot;&gt;http://www.itpub.net/viewthread.php?tid=1265917&amp;amp;extra=&amp;amp;page=1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;关于hint&lt;/p&gt;
&lt;p&gt;前几天看看坛子上有人问关于hint的问题，加了hint到底能不能保证执行计划？应不应该用hint？等等。&lt;/p&gt;
&lt;p&gt;所以我想写一点关于Hint的小介绍， 好久不来itpub了，算抛块砖吧，希望把玉引出来。。。。。。也可以拍砖。&lt;/p&gt;
&lt;p&gt;oracle的hint是人人知道的啦，那加了hint到底能不能保证执行计划？我的看法是能保证，但前提是你用的对。&lt;br /&gt;
到底应不应该用？这个要看具体情况，看是什么样的系统，当然我在自己做测试的时候用Hint是用的很多的。&lt;/p&gt;
&lt;p&gt;下面关于Hint浅议几个话题：&lt;/p&gt;
&lt;p&gt;1，首先Hint是怎么工作的。&lt;/p&gt;
&lt;p&gt;我先跑个简单的SQL，&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;alter system flush shared_pool;&lt;br /&gt;
alter session set events &amp;#8216;10053 trace name context forever, level 1&amp;#8242;;&lt;/p&gt;
&lt;p&gt;select e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这个是执行计划：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation                      | Name             | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT               |                  |       |       |     3 |           |&lt;br /&gt;
| 1   |  TABLE ACCESS BY INDEX ROWID   | EMPLOYEES        |    10 |   110 |     1 |  00:00:01 |&lt;br /&gt;
| 2   |   NESTED LOOPS                 |                  |    10 |   270 |     3 |  00:00:01 |&lt;br /&gt;
| 3   |    TABLE ACCESS BY INDEX ROWID | DEPARTMENTS      |     1 |    16 |     2 |  00:00:01 |&lt;br /&gt;
| 4   |     INDEX RANGE SCAN           | DEPART_NAME_IND  |     1 |       |     1 |  00:00:01 |&lt;br /&gt;
| 5   |    INDEX RANGE SCAN            | EMP_DEPARTMENT_IX|    10 |       |     0 |           |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
Predicate Information:&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
4 &amp;#8211; access(&amp;#8220;D&amp;#8221;.&amp;#8221;DEPARTMENT_NAME&amp;#8221;=:SYS_B_0)&lt;br /&gt;
5 &amp;#8211; access(&amp;#8220;E&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221;=&amp;#8221;D&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221;&lt;img src=&quot;http://www.itpub.net/images/smilies/23.gif&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;然后看它的10053 trace，从trace里面可以清楚的看到在访问departments这个表的问题上，oracle对比了全表扫描和索引range scan,&lt;br /&gt;
最后觉得使用索引DEPART_NAME_IND是最好的。&lt;/p&gt;
&lt;p&gt;SINGLE TABLE ACCESS PATH&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
BEGIN Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
Column (#2): DEPARTMENT_NAME(VARCHAR2)&lt;br /&gt;
AvgLen: 12.00 NDV: 27 Nulls: 0 Density: 0.037037&lt;br /&gt;
Table: DEPARTMENTS  Alias: D&lt;br /&gt;
Card: Original: 27  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
END   Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Access Path: TableScan&lt;/span&gt;&lt;br /&gt;
Cost:  3.01  Resp: 3.01  Degree: 0&lt;br /&gt;
Cost_io: 3.00  Cost_cpu: 41547&lt;br /&gt;
Resp_io: 3.00  Resp_cpu: 41547&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Access Path: index (AllEqRange)&lt;/span&gt;&lt;br /&gt;
Index: DEPART_NAME_IND&lt;br /&gt;
resc_io: 2.00  resc_cpu: 14613&lt;br /&gt;
ix_sel: 0.037037  ix_sel_with_filters: 0.037037&lt;br /&gt;
Cost: 2.00  Resp: 2.00  Degree: 1&lt;br /&gt;
******** Begin index join costing ********&lt;br /&gt;
****** trying bitmap/domain indexes ******&lt;br /&gt;
Access Path: index (AllEqRange)&lt;br /&gt;
Index: DEPART_NAME_IND&lt;br /&gt;
resc_io: 1.00  resc_cpu: 7321&lt;br /&gt;
ix_sel: 0.037037  ix_sel_with_filters: 0.037037&lt;br /&gt;
Cost: 1.00  Resp: 1.00  Degree: 0&lt;br /&gt;
****** finished trying bitmap/domain indexes ******&lt;br /&gt;
Access Path: index (FullScan)&lt;br /&gt;
Index: DEPT_ID_PK&lt;br /&gt;
resc_io: 1.00  resc_cpu: 12521&lt;br /&gt;
ix_sel: 1  ix_sel_with_filters: 1&lt;br /&gt;
Cost: 1.00  Resp: 1.00  Degree: 0&lt;br /&gt;
******** Cost index join ********&lt;br /&gt;
Index join: Considering index join to index DEPART_NAME_IND&lt;br /&gt;
Index join: Joining index DEPT_ID_PK&lt;br /&gt;
Ix HA Join&lt;br /&gt;
Outer table:&lt;br /&gt;
resc: 1.00  card 1.00  bytes: 22  deg: 1  resp: 1.00&lt;br /&gt;
Inner table: &amp;lt;no name&amp;gt;&lt;br /&gt;
resc: 1.25  card: 27.00  bytes: 14  deg: 1  resp: 1.25&lt;br /&gt;
using dmeth: 2  #groups: 1&lt;br /&gt;
Cost per ptn: 0.50  #ptns: 1&lt;br /&gt;
hash_area: 0 (max=0)   Hash join: Resc: 2.75  Resp: 2.75  [multiMatchCost=0.00]&lt;br /&gt;
******** Index join cost ********&lt;br /&gt;
Cost: 2.75&lt;br /&gt;
******** End index join costing ********&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Best:: AccessPath: IndexRange  Index: DEPART_NAME_IND&lt;br /&gt;
Cost: 2.00  Degree: 1  Resp: 2.00  Card: 1.00  Bytes: 0&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;好，现在我想走departments的全表扫描，很简单，加个full(d)的Hint：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;alter system flush shared_pool;&lt;br /&gt;
alter session set events &amp;#8216;10053 trace name context forever, level 1&amp;#8242;;&lt;/p&gt;
&lt;p&gt;select /*+ full(d) */ e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;执行计划改成了全表扫描：&lt;br /&gt;
============&lt;br /&gt;
Plan Table&lt;br /&gt;
============&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation                    | Name             | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT             |                  |       |       |     4 |           |&lt;br /&gt;
| 1   |  TABLE ACCESS BY INDEX ROWID | EMPLOYEES        |    10 |   110 |     1 |  00:00:01 |&lt;br /&gt;
| 2   |   NESTED LOOPS               |                  |    10 |   270 |     4 |  00:00:01 |&lt;br /&gt;
| 3   |    TABLE ACCESS FULL         | DEPARTMENTS      |     1 |    16 |     3 |  00:00:01 |&lt;br /&gt;
| 4   |    INDEX RANGE SCAN          | EMP_DEPARTMENT_IX|    10 |       |     0 |           |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;然后我们看看10053 trace，我们会看到这时候trace里只能看到关于TableScan的cost计算：&lt;br /&gt;
SINGLE TABLE ACCESS PATH&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
BEGIN Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
Column (#2): DEPARTMENT_NAME(VARCHAR2)&lt;br /&gt;
AvgLen: 12.00 NDV: 27 Nulls: 0 Density: 0.037037&lt;br /&gt;
Table: DEPARTMENTS  Alias: D&lt;br /&gt;
Card: Original: 27  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
END   Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt; Access Path: TableScan&lt;/span&gt;&lt;br /&gt;
Cost:  3.01  Resp: 3.01  Degree: 0&lt;br /&gt;
Cost_io: 3.00  Cost_cpu: 41547&lt;br /&gt;
Resp_io: 3.00  Resp_cpu: 41547&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt; Best:: AccessPath: TableScan&lt;/span&gt;&lt;br /&gt;
Cost: 3.01  Degree: 1  Resp: 3.01  Card: 1.00  Bytes: 0&lt;/p&gt;
&lt;p&gt;默认情况下，只要一个SQL的所有的可能的access path和join path不是特别多，oracle的query optimizer都会考虑所有的可能的计划，进行比较，得出最佳方案。这是query optimizer的基本功能之一，我们都知道。。。&lt;br /&gt;
而hint的作用就是要求query optimizer在考虑的过程中只考虑某些access或Join path，或者排除某些access或Join path。所以简单的说，&lt;span style=&quot;color: blue;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;HINT的工作方式就是给oracle加限制。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;（只不过有些Hint对oracle加的限制不像限制它智能full table scan这样的直观，比如修改参数用的OPT_PARAM，修改统计信息估计的CARDINALITY， 控制是把子查询数据放在内存还是放在临时空间的MATERIALIZE，等等，不过都是给oracle加人为的限制。）&lt;/p&gt;
&lt;p&gt;这种工作模式在我看来还是比较科学的，只要是合理的使用了hint, 应该是可以保证执行计划按照我们想要的方式走的。&lt;br /&gt;
（但是要想合理的使用Hint还是需要点练习的 &lt;img src=&quot;http://www.itpub.net/images/smilies/14.gif&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt; )&lt;/p&gt;
&lt;p&gt;到这里，让我们考虑一下一个经常被讨论的问题：到底该不该在系统里使用Hint？&lt;br /&gt;
我个人的观点是，&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;把hint作为最后的手段&lt;/span&gt;&lt;/span&gt;，只要我能通过其他方式把问题解决， 一般我不会考虑使用Hint。（这里的其他方式比如改表的结构，改sql，改统计信息收集的策略。。。），&lt;/p&gt;
&lt;p&gt;对我来说，短期来说Hint也许是个解决问题的最快方案，但它从长远来看会引入风险。&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;因为我没法保证以后数据分布情况不会变化，&lt;br /&gt;
我也没法保证以后表结构不会变化，&lt;br /&gt;
我也没法保证以后数据库不会升级。&lt;/span&gt;&lt;br /&gt;
而以上这些情况都会导致加了Hint的SQL性能变差，而每一种这种变差，都有可能变成业务级别的故障。&lt;br /&gt;
（遥想当年，我也是在很多系统加了很多hint滴，为这些系统默哀一下。。。）&lt;/p&gt;
&lt;p&gt;但这个问题是因系统而异的，比如在线事务系统一般是很少用Hint的，因为SQL一般都比较简单，oracle自己就可以处理的很好。&lt;br /&gt;
但是数据仓库类型的系统可能用hint就会都一些，我以前在ETL的语句里就加过不少，原因很简单，这里的表好多好大，SQL都好长好复杂，优化好难好挑战，我加了Hint可能会为将来引入风险，但是我不加的话估计连现在都保不住。&lt;/p&gt;
&lt;p&gt;从心理的角度分析，我觉得（我就是觉得哈，我不是心理专家)，&lt;br /&gt;
1） 倾向于加hint的人在精神深层次里存在一种对oracle的不信任，&lt;br /&gt;
2） 不倾向于加hint的人在精神深层次里存在一种对oracle的信任，&lt;br /&gt;
（我本人就经历过从最开始的对oracle的盲目信任，到对oracle的盲目不信任，再到对oracle的针对性不信任，再到对oracle的针对性信任。。。）&lt;br /&gt;
我想信任也好，不信任也好，不过是个个人风格问题，当一个人在这个工作里混了5，6，7，8年以后，总会对oracle方面的工作或多或少产生点方法论，世界观之类的东西，&lt;br /&gt;
有的人信任oracle多点，有的人不信任多点，这纯粹是个风格问题，无所谓对错。回到用不用Hint这个话题，这里也存在一个风格的问题。&lt;br /&gt;
不喜欢加Hint的人，像我，就会找一堆不加的好处。喜欢加hint的人可能就会找出一堆加的好处。&lt;/p&gt;
&lt;p&gt;这就像你去做领导，&lt;br /&gt;
1）有的领导是喜欢给team members定好一个完整的流程，什么都要严格的按流程来，对做事的每一个细节都要监控到。&lt;br /&gt;
2）有的领导是喜欢定个high level的目标和规定，然后让team member放手去做。&lt;br /&gt;
这也纯粹是个公司的或个人的风格问题.&lt;br /&gt;
&lt;span style=&quot;color: navy;&quot;&gt;&lt;br /&gt;
对oracle的管理也像治家，治公司，治国，风格或有不同，实在说不上什么是一定好，什么是一定不好的。每个人都可以形成自己的方法论，每个人到了一定阶段都会形成自己的方法论，因人而因，因地制宜，运用之道，存乎一心。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;继续，&lt;br /&gt;
前面看到hint的工作方式还是很科学的，但平时自己加的Hint总是不起作用，这一般都是hint用错了。&lt;/p&gt;
&lt;p&gt;例如这个例子：&lt;/p&gt;
&lt;p&gt;select e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;Here is the plan:&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation                      | Name             | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT               |                  |       |       |     3 |           |&lt;br /&gt;
| 1   |  TABLE ACCESS BY INDEX ROWID   | EMPLOYEES        |    10 |   110 |     1 |  00:00:01 |&lt;br /&gt;
| 2   |   NESTED LOOPS                 |                  |    10 |   270 |     3 |  00:00:01 |&lt;br /&gt;
| 3   |    TABLE ACCESS BY INDEX ROWID | DEPARTMENTS      |     1 |    16 |     2 |  00:00:01 |&lt;br /&gt;
| 4   |    &lt;span style=&quot;color: blue;&quot;&gt; INDEX RANGE SCAN           | DEPART_NAME_IND&lt;/span&gt; |     1 |       |     1 |  00:00:01 |&lt;br /&gt;
| 5   |    INDEX RANGE SCAN            | EMP_DEPARTMENT_IX|    10 |       |     0 |           |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;/p&gt;
&lt;p&gt;对于DEPART_NAME_IND这个索引, 如果我不想让它走range scan，让它走fast full index scan，行不行？&lt;br /&gt;
那我试着加INDEX_FFS这个Hint：&lt;br /&gt;
select&lt;span style=&quot;color: blue;&quot;&gt; /*+ INDEX_FFS(D (&amp;#8220;DEPARTMENTS&amp;#8221;.&amp;#8221;DEPARTMENT_NAME&amp;#8221;)) */ &lt;/span&gt;e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation                     | Name              | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT              |                   |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID  | EMPLOYEES         |    10 |   110 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                |                   |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |     1 |    16 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  4 |     &lt;span style=&quot;color: blue;&quot;&gt;INDEX RANGE SCAN          | DEPART_NAME_IND &lt;/span&gt; |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |    INDEX RANGE SCAN           | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;结果没有作用，按理说这么简单的语句加Hint是很少不生效的，问题就在于对fast full index scan的理解，&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;fast full index scan这种access path只能用在当你能够从index上取得所有需要的信息，而不需要访问表的时候&lt;/span&gt;，而这里最后很定是&lt;br /&gt;
需要访问DEPARTMENTS的，所以oracle优化器在考虑所有可能的执行计划的时候，完全就不会考虑到fast full index scan。&lt;br /&gt;
就好比oracle考虑的是a, b, c, d，而你要求的是e, 这样的Hint是不会生效的，你只能在a, b, c, d里面选。&lt;/p&gt;
&lt;p&gt;当然如果我们建个复合索引，fast full index scan就没问题了。&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;SQL&amp;gt; create index depart_name_id_ind on departments(department_id, department_name);&lt;/p&gt;
&lt;p&gt;索引已创建。&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; exec dbms_stats.gather_table_stats(user,&amp;#8217;DEPARTMENTS&amp;#8217;);&lt;/p&gt;
&lt;p&gt;PL/SQL 过程已成功完成。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;select &lt;span style=&quot;color: blue;&quot;&gt;/*+ INDEX_FFS(D (&amp;#8220;DEPARTMENTS&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221; &amp;#8220;DEPARTMENTS&amp;#8221;.&amp;#8221;DEPARTMENT_NAME&amp;#8221;)) */ &lt;/span&gt;e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 3172774359&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
| Id  | Operation                   | Name               | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
|   0 | SELECT STATEMENT            |                    |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES          |    10 |   110 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS              |                    |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |    &lt;span style=&quot;color: blue;&quot;&gt;INDEX FAST FULL SCAN     | DEPART_NAME_ID_IND&lt;/span&gt; |     1 |    16 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  4 |    INDEX RANGE SCAN         | EMP_DEPARTMENT_IX  |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;/p&gt;
&lt;p&gt;前面的例子说明使用hint需要多执行计划有一定的了解，但其实很多时候Hint不生效都是因为一些很简单的原因：用错了语法或者用错的地方：&lt;br /&gt;
hint的基本使用方法可以在oracle的sql reference里面看到：&lt;br /&gt;
&lt;a href=&quot;http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements006.htm#i35922&quot; target=&quot;_blank&quot;&gt;http://download.oracle.com/docs/ &amp;#8230; ments006.htm#i35922&lt;/a&gt;&lt;br /&gt;
这里也有oracle documented hint的列表，是个不错的参考的地方。&lt;/p&gt;
&lt;p&gt;PS: 如果要看undocumented的oracle hint，这里还不错：&lt;br /&gt;
&lt;a href=&quot;http://www.psoug.org/reference/hints.html&quot; target=&quot;_blank&quot;&gt;http://www.psoug.org/reference/hints.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;比较容易让人忽视的一点是要留意Hint的作用域，Hint一般都是在它所在的query block生效，所以如下的Hint是无效的：&lt;br /&gt;
select /*+ full(d) */ * from employees e where department_id in&lt;br /&gt;
(select department_id from departments d where d.department_name=&amp;#8217;IT&amp;#8217;);&lt;/p&gt;
&lt;p&gt;正确的用法是：&lt;br /&gt;
在departments所在的query block加hint&lt;br /&gt;
select * from employees e where department_id in&lt;br /&gt;
(select /*+ full(d) */ department_id from departments d where d.department_name=&amp;#8217;IT&amp;#8217;);&lt;/p&gt;
&lt;p&gt;或者定义query block的名字，然后再外围query block使用query block的名字。&lt;br /&gt;
select /*+ full(@qb1 d) */ * from employees e where department_id in&lt;br /&gt;
(select /*+ qb_name (qb1) */ department_id from departments d where d.department_name=&amp;#8217;IT&amp;#8217;);&lt;/p&gt;
&lt;p&gt;介绍一些&lt;strong&gt;&lt;span style=&quot;font-size: small;&quot;&gt;次常用&lt;/span&gt;&lt;/strong&gt;的hint，&lt;br /&gt;
我们都熟悉那些常用的Hint，&lt;br /&gt;
比如用来调整access path的 （如full, index, parallel&amp;#8230;)，&lt;br /&gt;
调整join order的 （如order, leading&amp;#8230;),&lt;br /&gt;
调整join path的（use_nl, use_hash&amp;#8230;)&lt;br /&gt;
调整remote access的 （如driving_site)，&lt;br /&gt;
调整查询转化的（如rewrite, unnest, merge),&lt;/p&gt;
&lt;p&gt;这些都是比较常用的，说起来没什么意思，现在说几个&amp;#8221;次常用&amp;#8221;的hint.&lt;/p&gt;
&lt;p&gt;1）&lt;strong&gt;&lt;span style=&quot;font-size: small;&quot;&gt;dynamic_sampling,&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
这个Hint在sql reference里面有介绍：&lt;br /&gt;
The DYNAMIC_SAMPLING hint instructs the optimizer how to control dynamic sampling to improve server performance by determining more accurate predicate selectivity and statistics for tables and indexes.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;drop table t1;&lt;br /&gt;
drop table t2;&lt;br /&gt;
create table t1 (x int, y int);&lt;br /&gt;
create index t1_xy on t1(x,y);&lt;/p&gt;
&lt;p&gt;create table t2 (x int);&lt;br /&gt;
create index t2_x on t2(x);&lt;/p&gt;
&lt;p&gt;insert into t1 select mod(rownum, 10), mod(rownum, 10) from dba_objects where rownum&amp;lt;=50000;&lt;br /&gt;
insert into t2 select mod(rownum, 50) from dba_objects where rownum&amp;lt;=50000;&lt;/p&gt;
&lt;p&gt;commit;&lt;/p&gt;
&lt;p&gt;exec dbms_stats.gather_table_stats(user,&amp;#8217;T1&amp;#8242;);&lt;br /&gt;
exec dbms_stats.gather_table_stats(user,&amp;#8217;T2&amp;#8242;);&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; set autotrace traceonly exp&lt;br /&gt;
SQL&amp;gt; select t1.x, t2.x from t1,t2&lt;br /&gt;
2  where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 4152676900&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT  |       |   501K|  3428K|    32  (29)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN        |       |   501K|  3428K|    32  (29)| 00:00:01 |&lt;br /&gt;
|*  2 |   INDEX RANGE SCAN| T1_XY |   496 |  2480 |    19   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |   INDEX RANGE SCAN| T2_X  |  1011 |  2022 |     4   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;Predicate Information (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=&amp;#8221;T1&amp;#8243;.&amp;#8221;X&amp;#8221;)&lt;br /&gt;
2 &amp;#8211; access(&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221;=1 AND &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;=1)&lt;br /&gt;
3 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=1)&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; select &lt;span style=&quot;color: red;&quot;&gt;/*+ dynamic_sampling(4) */&lt;/span&gt; t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 224376697&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT  |       |  5015K|    33M|   110  (80)| 00:00:02 |&lt;br /&gt;
|*  1 |  HASH JOIN        |       |  5015K|    33M|   110  (80)| 00:00:02 |&lt;br /&gt;
|*  2 |   INDEX RANGE SCAN| T2_X  |  1011 |  2022 |     4   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |   INDEX RANGE SCAN| T1_XY |  4963 | 24815 |    19   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;Predicate Information (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=&amp;#8221;T1&amp;#8243;.&amp;#8221;X&amp;#8221;)&lt;br /&gt;
2 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=1)&lt;br /&gt;
3 &amp;#8211; access(&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221;=1 AND &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;=1)&lt;/p&gt;
&lt;p&gt;Note&lt;br /&gt;
&amp;#8212;&amp;#8211;&lt;br /&gt;
- dynamic sampling used for this statement&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;那个执行计划更好一些？应该是第二个，&lt;/p&gt;
&lt;p&gt;这里的第一个执行计划把t1作为驱动表，t2作为被驱动表，因为oracle认为t1.x=1 and t1.y=1应该返回更少的行数。&lt;br /&gt;
oracle在判断t1.x=1 and t1.y=1的总行数 =&amp;gt; （t1.x=1的选择率 * t1.y=1的选择率）* t1行数 =&amp;gt; （0.1 * 0.1）* 50000 = 500 （计划里是496）&lt;br /&gt;
oracle在判断t2.x=1的总行数 =&amp;gt; t2.x=1的选择率 * t2行数 =&amp;gt; 0.02 * 50000 = 1000.&lt;/p&gt;
&lt;p&gt;所以oracle把t1作为驱动表是可以理解的，但问题是实际的数据分布t1.x总是等于t1.y，所以真实的数据t1.x=1 and t1.y=1的总行数 = t1.x=1的选择率 * t1行数 = 0.1 * 50000 = 5000 （计划里的4963) !&lt;/p&gt;
&lt;p&gt;为了让oracle认识到这一点，我们使用level 4的dynamic_sampling, dynamic_sampling level 4的意思是：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;Level 4: Apply dynamic sampling to all tables that meet Level 3 criteria, plus all&lt;br /&gt;
tables that have single-table predicates that reference 2 or more columns. The&lt;br /&gt;
number of blocks sampled is the default number of dynamic sampling blocks. For&lt;br /&gt;
unanalyzed tables, the number of blocks sampled is two times the default number&lt;br /&gt;
of dynamic sampling blocks&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;从level 4开始oracle开始对“tables that have single-table predicates that reference 2 or more columns” 这种情况开始采样，所以能够意识到真实的数据分布是什么样，所以我们&lt;br /&gt;
看到第二个是以t2为驱动表的。&lt;/p&gt;
&lt;p&gt;这种类似的问题在复杂的SQL里面会很常见。&lt;/p&gt;
&lt;p&gt;但是dynamic_sampling这个Hint会在oracle解析的时候产生额外的开销，我很少真的在代码里用，不过我经常在调优的时候用。&lt;br /&gt;
比如当我运行完这个SQL语句之后：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;select /*+ dynamic_sampling(4) */ t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;我会马上跟一个：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;select * from table(dbms_xplan.display_cursor(null, 0 , &amp;#8216;advanced&amp;#8217;));&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这样就可以得到为了实现这个比较好的计划所需要的所有的Hint，你如果要在系统里加hint, 动态采样+dbms_xplan.display_cursor是个捷径:&lt;/p&gt;
&lt;p&gt;/*+&lt;br /&gt;
BEGIN_OUTLINE_DATA&lt;br /&gt;
IGNORE_OPTIM_EMBEDDED_HINTS&lt;br /&gt;
OPTIMIZER_FEATURES_ENABLE(&amp;#8216;10.2.0.1&amp;#8242;)&lt;br /&gt;
ALL_ROWS&lt;br /&gt;
OUTLINE_LEAF(@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;))&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221; &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;))&lt;br /&gt;
LEADING(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
USE_HASH(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
END_OUTLINE_DATA&lt;br /&gt;
*/&lt;/p&gt;
&lt;p&gt;在真实使用的时候你必须把outline相关的和IGNORE_OPTIM_EMBEDDED_HINTS这个奇怪的Hint去掉，&lt;br /&gt;
也可以把OPTIMIZER_FEATURES_ENABLE(&amp;#8216;10.2.0.1&amp;#8242;)，ALL_ROWS去掉，因为这些环境不大会改变。&lt;/p&gt;
&lt;p&gt;然后可以把oracle自定义的query block去掉，如果你的sql有多个query block的话可能需要自己定义query block的名字（见我前面的帖子）&lt;/p&gt;
&lt;p&gt;我这个SQL最后留下这么几个hint就够了：&lt;br /&gt;
/*+&lt;br /&gt;
INDEX(&amp;#8220;T2&amp;#8243; (&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;))&lt;br /&gt;
INDEX(&amp;#8220;T1&amp;#8243; (&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221; &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;))&lt;br /&gt;
LEADING( &amp;#8220;T2&amp;#8243; &amp;#8220;T1&amp;#8243;)&lt;br /&gt;
USE_HASH(&amp;#8220;T1&amp;#8243;)&lt;br /&gt;
*/&lt;/p&gt;
&lt;p&gt;还有一个问题，就是有的SQL一跑就是几天，甚至会影响整个系统，你优化的时候不可能把它跑一遍，所以也不能用dbms_xplan.display_cursor，那你可以考虑这个方法。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;alter session set events &amp;#8216;10132 trace name context forever, level 1&amp;#8242;;&lt;/span&gt;&lt;br /&gt;
这里使用10053效果也类似，但我发现10053只有在hard parse的时候才生成trace，所以一般用10053之前可能需要flush shared_pool。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;set autotrace traceonly exp&lt;br /&gt;
select /*+ dynamic_sampling(4) */ t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;于是在trace里你可以看到下面的内容：&lt;br /&gt;
sql_id=62dhqxdq49t6a.&lt;br /&gt;
Current SQL statement for this session:&lt;br /&gt;
EXPLAIN PLAN SET STATEMENT_ID=&amp;#8217;PLUS1777&amp;#8242; FOR select /*+ dynamic_sampling(4) */ t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x&lt;/p&gt;
&lt;p&gt;============&lt;br /&gt;
Plan Table&lt;br /&gt;
============&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation          | Name    | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT   |         |       |       |   110 |           |&lt;br /&gt;
| 1   |  HASH JOIN         |         | 4897K |   33M |   110 |  00:00:02 |&lt;br /&gt;
| 2   |   INDEX RANGE SCAN | T2_X    |  1011 |  2022 |     4 |  00:00:01 |&lt;br /&gt;
| 3   |   INDEX RANGE SCAN | T1_XY   |  4963 |   24K |    19 |  00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
Predicate Information:&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=&amp;#8221;T1&amp;#8243;.&amp;#8221;X&amp;#8221;)&lt;br /&gt;
2 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=1)&lt;br /&gt;
3 &amp;#8211; access(&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221;=1 AND &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;=1)&lt;/p&gt;
&lt;p&gt;Content of other_xml column&lt;br /&gt;
===========================&lt;br /&gt;
db_version     : 10.2.0.1&lt;br /&gt;
parse_schema   : HR&lt;br /&gt;
dynamic_sampling: yes&lt;br /&gt;
plan_hash      : 224376697&lt;br /&gt;
Outline Data:&lt;br /&gt;
/*+&lt;br /&gt;
BEGIN_OUTLINE_DATA&lt;br /&gt;
IGNORE_OPTIM_EMBEDDED_HINTS&lt;br /&gt;
OPTIMIZER_FEATURES_ENABLE(&amp;#8216;10.2.0.1&amp;#8242;)&lt;br /&gt;
ALL_ROWS&lt;br /&gt;
OUTLINE_LEAF(@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;))&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221; &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;))&lt;br /&gt;
LEADING(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
USE_HASH(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
END_OUTLINE_DATA&lt;br /&gt;
*/&lt;/p&gt;
&lt;p&gt;关于这个Hint: &lt;span style=&quot;color: blue;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;swap_join_inputs&lt;/span&gt;&lt;/span&gt;,&lt;br /&gt;
这是一个undocumented Hint,在官方文档里面看不到，它的作用是帮我们调整join的顺序。&lt;br /&gt;
一般调整Join的顺序用leading或者order就可以了，但是看看下面的4表连接例子：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;select e.last_name, d.department_name, j.job_title&lt;br /&gt;
from employees e, departments d, jobs j, locations l&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and e.job_id = j.job_id&lt;br /&gt;
and d.location_id=l.location_id&lt;br /&gt;
and j.job_title=&amp;#8217;Programmer&amp;#8217;&lt;br /&gt;
and l.city=&amp;#8217;Beijing&amp;#8217;&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;&lt;br /&gt;
;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 3164695383&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
| Id  | Operation                      | Name              | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
|   0 | SELECT STATEMENT               |                   |     1 |    78 |     5   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  NESTED LOOPS                  |                   |     1 |    78 |     5   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                 |                   |    10 |   510 |     4   (0)| 00:00:01 |&lt;br /&gt;
|   3 |    NESTED LOOPS                |                   |     1 |    31 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   4 |     TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |     1 |    19 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |      INDEX RANGE SCAN          | DEPART_NAME_IND   |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  6 |     TABLE ACCESS BY INDEX ROWID| LOCATIONS         |     1 |    12 |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  7 |      INDEX RANGE SCAN          | LOC_CITY_IX       |     1 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
|   8 |    TABLE ACCESS BY INDEX ROWID | EMPLOYEES         |    10 |   200 |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  9 |     INDEX RANGE SCAN           | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
|* 10 |   TABLE ACCESS BY INDEX ROWID  | JOBS              |     1 |    27 |     1   (0)| 00:00:01 |&lt;br /&gt;
|* 11 |    INDEX UNIQUE SCAN           | JOB_ID_PK         |     1 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这里的连接顺序是&lt;br /&gt;
1） departments先和location连，departments作为驱动表。&lt;br /&gt;
2） 上一步的结果集和employees连， 上一步的结果集作为驱动表。&lt;br /&gt;
3） 上一步的结果集和JOBS连， 上一步的结果集作为驱动表。&lt;/p&gt;
&lt;p&gt;这里有oracle的一个规则，就是如果前面一步的Join的结果在和其他表做连接，那么默认情况下总是把前面一步的Join的结果作为驱动者，&lt;/p&gt;
&lt;p&gt;CBO本身一般不会基于cost的考虑来打破这个规则，所以如果我想要的连接顺序变成下面这样，似乎有点麻烦，因为leading 和order这样的Hint是做不到的：&lt;br /&gt;
1） departments先和location连，departments作为驱动表。&lt;br /&gt;
2） 上一步的结果集和employees连， employees作为驱动表。&lt;br /&gt;
3） 上一步的结果集和JOBS连， JOBS作为驱动表。&lt;/p&gt;
&lt;p&gt;你可以试一下swap_join_inputs这个Hint，swap_join_inputs就是用来修改上面说的这个规则的：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;select&lt;br /&gt;
/*+ leading(d l e j)&lt;br /&gt;
use_nl(l)&lt;br /&gt;
use_hash(e)&lt;br /&gt;
swap_join_inputs(e)&lt;br /&gt;
use_hash(j)&lt;br /&gt;
swap_join_inputs(j)&lt;br /&gt;
*/&lt;br /&gt;
e.last_name, d.department_name, j.job_title&lt;br /&gt;
from employees e, departments d, jobs j, locations l&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and e.job_id = j.job_id&lt;br /&gt;
and d.location_id=l.location_id&lt;br /&gt;
and j.job_title=&amp;#8217;Programmer&amp;#8217;&lt;br /&gt;
and l.city=&amp;#8217;Beijing&amp;#8217;&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;&lt;br /&gt;
;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation                       | Name            | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT                |                 |     1 |    78 |    10  (10)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN                      |                 |     1 |    78 |    10  (10)| 00:00:01 |&lt;br /&gt;
|*  2 |   TABLE ACCESS FULL             | JOBS            |     1 |    27 |     3   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |   HASH JOIN                     |                 |    10 |   510 |     7  (15)| 00:00:01 |&lt;br /&gt;
|   4 |    TABLE ACCESS FULL            | EMPLOYEES       |   107 |  2140 |     3   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |    TABLE ACCESS BY INDEX ROWID  | LOCATIONS       |     1 |    12 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   6 |     NESTED LOOPS                |                 |     1 |    31 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   7 |      TABLE ACCESS BY INDEX ROWID| DEPARTMENTS     |     1 |    19 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  8 |       INDEX RANGE SCAN          | DEPART_NAME_IND |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  9 |      INDEX RANGE SCAN           | LOC_CITY_IX     |     1 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;你也许奇怪为什么我要加use_hash(e)这样的Hint，因为我发现如果我使用其他join的方式，swap_join_inputs一般是不生效的。&lt;br /&gt;
由于swap_join_inputs是个没有官方记载的Hint，所以我还不能肯定的说swap_join_inputs只支持hash join, 这一点欢迎大家都来测一下。&lt;/p&gt;
&lt;p&gt;但是如果你想连接顺序变成这样该怎么搞？&lt;br /&gt;
1） departments和location连。&lt;br /&gt;
2） employees和jobs去连接&lt;br /&gt;
3） 第一步的结果和第二步的结果做连接，第二步的结果作为驱动。&lt;/p&gt;
&lt;p&gt;(⊙o⊙)… 别难为我了，写成子查询吧。。。&lt;/p&gt;
&lt;p&gt;SWAP_JOIN_INPUTS这个Hint还可以用在调整外连接的连接顺序，下面这里例子我在wabjtam123 的帖子里贴过的，&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; set autotrace traceonly&lt;br /&gt;
SQL&amp;gt; select&lt;br /&gt;
2  t2.c1, t2.c2&lt;br /&gt;
3  from t1,t2 where t2.c1(+)=t1.c1;&lt;/p&gt;
&lt;p&gt;未选定行&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 1823443478&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT   |      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN OUTER   |      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|   2 |   TABLE ACCESS FULL| T1   |     1 |    13 |     2   (0)| 00:00:01 |&lt;br /&gt;
|   3 |   TABLE ACCESS FULL| T2   |     1 |    26 |     2   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;要调整outer join的连接顺序，使用leading是不够的，oracle在处理outer join的连接顺序的时候会有些小固执，需要加上USE_HASH&lt;br /&gt;
和SWAP_JOIN_INPUTS：&lt;/p&gt;
&lt;p&gt;SQL&amp;gt;&lt;br /&gt;
SQL&amp;gt; select&lt;br /&gt;
2  /*+&lt;br /&gt;
3      LEADING(t1 t2)&lt;br /&gt;
4      USE_HASH(t2)&lt;br /&gt;
5      SWAP_JOIN_INPUTS(t2)&lt;br /&gt;
6  */&lt;br /&gt;
7  t2.c1, t2.c2&lt;br /&gt;
8  from t1,t2 where t2.c1(+)=t1.c1;&lt;/p&gt;
&lt;p&gt;未选定行&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 312430291&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT      |      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN RIGHT OUTER|      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|   2 |   TABLE ACCESS FULL   | T2   |     1 |    26 |     2   (0)| 00:00:01 |&lt;br /&gt;
|   3 |   TABLE ACCESS FULL   | T1   |     1 |    13 |     2   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;font-size: small;&quot;&gt;query block的名字&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这段的实际应用意义不大，研究这个主要为了好玩。&lt;/p&gt;
&lt;p&gt;前面提到我们可以用qb_name这个hint来定义SQL里面的query block的名字，实际上如果我们多看看&lt;br /&gt;
dbms_xplan.display_cursor的advanced模式的输出，或者看看10053 trace，或者看看10132 trace，就能发现其实oracle的CBO会&lt;br /&gt;
自己定义query block的名字，而且你会发现对于固定的SQL，这些query block的名字都是固定的。&lt;/p&gt;
&lt;p&gt;这里打算介绍一下oracle是如何确定这些query block名字的，这已经超出了hint的范畴，但是如果你看到oracle给你列出这样的一条Hint，&lt;br /&gt;
了解query block的命名的由来对你读懂这个hint是有帮助的：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;LEADING(@&amp;#8221;SEL$F5BB74E1&amp;#8243; &amp;#8220;D&amp;#8221;@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;EMPLOYEES&amp;#8221;@&amp;#8221;SEL$2&amp;#8243;) &lt;/span&gt;&lt;br /&gt;
&amp;#8211;如果SQL多次出现employees这张表，你知道这个Hint是指哪个employees么？&lt;/p&gt;
&lt;p&gt;其实一般来说，oracle对query block的命名还是很直观的，&lt;br /&gt;
如果是一个select，那么就命名为SEL$n，这里的n是1，2，3&amp;#8230;&lt;br /&gt;
如果是delete，就命名为DEL$n，是update，就命名为UPD$n，是insert，就叫INS$n, 是merge，就叫MISC$n&amp;#8230;&lt;/p&gt;
&lt;p&gt;下面我举出两个例子，一个select, 一个delete，其他的大家可以自己去试。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;explain plan for&lt;br /&gt;
select * from employees where salary = (select max(salary) from employees);&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$1&lt;/span&gt; / EMPLOYEES@SEL$1&lt;br /&gt;
2 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$2&lt;/span&gt;&lt;br /&gt;
3 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$2&lt;/span&gt; / EMPLOYEES@SEL$2&lt;/p&gt;
&lt;p&gt;explain plan for&lt;br /&gt;
delete from employees;&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;br /&gt;
Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;DEL$1&lt;/span&gt;&lt;br /&gt;
2 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;DEL$1&lt;/span&gt; / EMPLOYEES@DEL$1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;那为什么会出现类似于SEL$F5BB74E1这样的query block呢？这是因为oracle做了sql转化，我们知道oracle处于性能考虑会&lt;br /&gt;
把一些子查询转化为表与表连接的模式，SQL转化是个比较有意思的话题，包含的东西也很多（不仅仅针对子查询），&lt;br /&gt;
对于子查询而言，就是当你的SQL包含了子查询或者视图，oracle会对你的SQL进行转化，当然这种转化在10g里是基于cost的，也就是说如果转化后发现cost太高，这个转化就不会被采用。&lt;/p&gt;
&lt;p&gt;对于oracle的SQL转化主要是做：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;1） 转化SPJ (select + project + join) view&lt;br /&gt;
2） unnest Subquery&lt;br /&gt;
3） merge Complex View （mergable complex view的定义可见于oracle performance tuning guide)&lt;br /&gt;
4） Predicate Pushing， or expense, 物化视图重写，等。。。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;那么当转化发生后，SQL的结构就变了，所以oracle会为转化后的SQL生成新的query block，为了和没有发生转化的SQL有所区别，&lt;br /&gt;
oracle在这里采用比较特殊的格式。&lt;/p&gt;
&lt;p&gt;转化后oracle会把原来的一个外围的query block（假如名字是a), 和一个内部的query block(假如名字是b), 转化生成的新的query block的名字应该是a 和 b 的hash函数。&lt;/p&gt;
&lt;p&gt;看看下面的例子：&lt;br /&gt;
SQL1，这是一个多层嵌套，每个嵌套的子查询都可以被转化，我们能看到oracle在做完转化后生成的新的query block为SEL$9C113579。&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb1) */ * from&lt;br /&gt;
(select /*+ qb_name(qb2) */ * from&lt;br /&gt;
(select /*+ qb_name(qb3) */ * from employees));&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$9C113579&lt;/span&gt; / EMPLOYEES@QB3&lt;/p&gt;
&lt;p&gt;SQL2，是SQL1的第二层嵌套的查询，可以看到转化后生成的query block名字是SEL$1B0F72FE&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb2) */ * from&lt;br /&gt;
(select /*+ qb_name(qb3) */ * from employees);&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$1B0F72FE&lt;/span&gt; / EMPLOYEES@QB3&lt;/p&gt;
&lt;p&gt;SQL3，最外面得查询还是叫qb1，在里面随便套了一个子查询，但是我们把第二层查询的名字定义为SEL$1B0F72FE。&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb1) */ * from&lt;br /&gt;
(select /*+ qb_name(SEL$1B0F72FE) */ * from departments);&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$9C113579&lt;/span&gt; / EMPLOYEES@SEL$1B0F72FE&lt;/p&gt;
&lt;p&gt;可以看到转化后的query block的名字是SEL$9C113579，和我们的第一个SQL转化后得到的query block名字一致，这就可以证明，当oracle对SQL的子查询进行了转化后，&lt;br /&gt;
会生成新的query block的名字，这个名字是由原来的外围query block名字和原来的内存query block名字决定的，估计是一个hash 函数。&lt;/p&gt;
&lt;p&gt;如果我们把外面的query block名字改掉，得到的新的转化后的query block名字就会变了：&lt;/p&gt;
&lt;p&gt;explain plan for&lt;br /&gt;
select /*+ qb_name(qbnew) */ * from&lt;br /&gt;
(select /*+ qb_name(SEL$1B0F72FE) */ * from departments);&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$90C23CFB&lt;/span&gt; / DEPARTMENTS@SEL$1B0F72FE  &amp;#8211;变了&lt;/p&gt;
&lt;p&gt;下面这个例子可以看出，我把第二层的子查询做了一些改动，又套上了一些其他的子查询，但是使用no_merge hint来避免里面的子查询被oracle的CBO转化掉：&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb1) */ * from&lt;br /&gt;
(select /*+ qb_name(SEL$1B0F72FE) */ * from employees where department_id in&lt;br /&gt;
(select /*+ no_merge */ max(department_id) from departments where location_id in&lt;br /&gt;
(select /*+ no_merge */ max(location_id) from locations)));&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$9C113579&lt;/span&gt; / EMPLOYEES@SEL$1B0F72FE&lt;br /&gt;
2 &amp;#8211; SEL$9C113579 / EMPLOYEES@SEL$1B0F72FE&lt;br /&gt;
3 &amp;#8211; SEL$1&lt;br /&gt;
4 &amp;#8211; SEL$1        / DEPARTMENTS@SEL$1&lt;br /&gt;
5 &amp;#8211; SEL$1        / DEPARTMENTS@SEL$1&lt;br /&gt;
6 &amp;#8211; SEL$2&lt;br /&gt;
7 &amp;#8211; SEL$2        / LOCATIONS@SEL$2&lt;/p&gt;
&lt;p&gt;可以看到，即使把内层的SQL做了这么多改变，最终转化出来的query block的名字还叫SEL$9C113579。&lt;/p&gt;
&lt;p&gt;最后看一个特殊的例子：&lt;/p&gt;
&lt;p&gt;这里是一个简单的2个表连接，没有子查询，但是我们可以看到在query block的名字是SEL$58A6D7F6，和我前面说的规则并不一样，为什么会这样？&lt;/p&gt;
&lt;p&gt;explain plan for&lt;br /&gt;
select department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
| Id  | Operation                     | Name             | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
|   0 | SELECT STATEMENT              |                  |     4 |    76 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID  | DEPARTMENTS      |     4 |    28 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                |                  |     4 |    76 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   3 |    TABLE ACCESS BY INDEX ROWID| LOCATIONS        |     1 |    12 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  4 |     INDEX RANGE SCAN          | LOC_CITY_IX      |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |    INDEX RANGE SCAN           | DEPT_LOCATION_IX |     4 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: red;&quot;&gt; 1 &amp;#8211; SEL$58A6D7F6 / D@SEL$1&lt;br /&gt;
3 &amp;#8211; SEL$58A6D7F6 / L@SEL$1&lt;br /&gt;
4 &amp;#8211; SEL$58A6D7F6 / L@SEL$1&lt;br /&gt;
5 &amp;#8211; SEL$58A6D7F6 / D@SEL$1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;原因在于这个SQL使用了ANSI的表连接语法，oracle在解析“join locations l on”这样的条件的时候会把它看做是一个子查询，于是乎会做转化，于是乎生成SEL$58A6D7F6这样的query block名字。&lt;/p&gt;
&lt;p&gt;在10053 trace里面会看到(VIEW MERGE SEL$2; SEL$1)这样的字样， 然后query被转化为：&lt;br /&gt;
select department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;&lt;/p&gt;
&lt;p&gt;10053 trace的部分内容：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;SQL:******* UNPARSED QUERY IS *******&lt;br /&gt;
SELECT &amp;#8220;D&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221; &amp;#8220;DEPARTMENT_ID&amp;#8221; FROM &amp;#8220;HR&amp;#8221;.&amp;#8221;DEPARTMENTS&amp;#8221; &amp;#8220;D&amp;#8221;,&amp;#8221;HR&amp;#8221;.&amp;#8221;LOCATIONS&amp;#8221; &amp;#8220;L&amp;#8221; WHERE &amp;#8220;L&amp;#8221;.&amp;#8221;CITY&amp;#8221;=&amp;#8217;Beijing&amp;#8217; AND &amp;#8220;D&amp;#8221;.&amp;#8221;LOCATION_ID&amp;#8221;=&amp;#8221;L&amp;#8221;.&amp;#8221;LOCATION_ID&amp;#8221;&lt;br /&gt;
Query block (04B6A5E0) unchanged&lt;br /&gt;
Registered qb: SEL$58A6D7F6 0&amp;#215;4b6a5e0 (&lt;span style=&quot;color: red;&quot;&gt;VIEW MERGE SEL$2; SEL$1&lt;/span&gt;)&lt;br /&gt;
signature (): qb_name=SEL$58A6D7F6 nbfros=2 flg=0&lt;br /&gt;
fro(0): flg=0 objn=51905 hint_alias=&amp;#8221;D&amp;#8221;@&amp;#8221;SEL$1&amp;#8243;&lt;br /&gt;
fro(1): flg=0 objn=51900 hint_alias=&amp;#8221;L&amp;#8221;@&amp;#8221;SEL$1&amp;#8243;&lt;br /&gt;
&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&lt;br /&gt;
&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&lt;br /&gt;
****************&lt;br /&gt;
QUERY BLOCK TEXT&lt;br /&gt;
****************&lt;br /&gt;
select department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这对我们有什么影响吗？ 其实影响不大，我前面也说这一段不是为了使用，仅仅为了好玩，不过假如上面的SQL作为我们下面语句的子查询，并且我想让表locations走全表扫描，我按理应该可以这样写hint：&lt;br /&gt;
explain plan for&lt;br /&gt;
select &lt;span style=&quot;color: red;&quot;&gt;/*+ full(@inner l) */&lt;/span&gt; * from employees where department_id in&lt;br /&gt;
(select &lt;span style=&quot;color: red;&quot;&gt;/*+ qb_name(inner) */&lt;/span&gt; department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;);&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
| Id  | Operation                         | Name              | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
|   0 | SELECT STATEMENT                  |                   |    39 |  3159 |     6  (17)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID      | EMPLOYEES         |    10 |   680 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                    |                   |    39 |  3159 |     6  (17)| 00:00:01 |&lt;br /&gt;
|   3 |    VIEW                           | VW_NSO_1          |     4 |    52 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   4 |     HASH UNIQUE                   |                   |     4 |    76 |            |          |&lt;br /&gt;
|   5 |      TABLE ACCESS BY INDEX ROWID  | DEPARTMENTS       |     4 |    28 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   6 |       NESTED LOOPS                |                   |     4 |    76 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   7 |        TABLE ACCESS BY INDEX ROWID| LOCATIONS         |     1 |    12 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  8 |         INDEX RANGE SCAN          | LOC_CITY_IX       |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  9 |        INDEX RANGE SCAN           | DEPT_LOCATION_IX  |     4 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
|* 10 |    INDEX RANGE SCAN               | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; SEL$78C29F24 / EMPLOYEES@SEL$2&lt;br /&gt;
3 &amp;#8211; SEL$49A70C8F / VW_NSO_1@SEL$78C29F24&lt;br /&gt;
4 &amp;#8211; SEL$49A70C8F&lt;br /&gt;
5 &amp;#8211; SEL$49A70C8F / D@SEL$1&lt;br /&gt;
7 &amp;#8211; SEL$49A70C8F / L@SEL$1&lt;br /&gt;
8 &amp;#8211; SEL$49A70C8F / L@SEL$1&lt;br /&gt;
9 &amp;#8211; SEL$49A70C8F / D@SEL$1&lt;br /&gt;
10 &amp;#8211; SEL$78C29F24 / EMPLOYEES@SEL$2&lt;/p&gt;
&lt;p&gt;但如你所见，hint似乎没有生效，这个原因就是尽管我们给&lt;br /&gt;
(select /*+ qb_name(inner) */ department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;)&lt;br /&gt;
这个子查询定义了query block的名字，但是因为这个是ANSI语法的连接，oracle会做一次转换，这次转化会给子查询生成一个新的query block(SEL$49A70C8F),&lt;br /&gt;
这进一步导致/*+ full(@inner l) */这个针对inner的Hint失效。&lt;/p&gt;
&lt;p&gt;要想达到目的的方法也很简单， 比如hint可以这么写：&lt;br /&gt;
select * from employees where department_id in&lt;br /&gt;
(select&lt;span style=&quot;color: red;&quot;&gt; /*+ full(l) */ &lt;/span&gt;department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;);&lt;/p&gt;
&lt;p&gt;或者既然已经知道了新的query block的名字，我们就可以这么写（当然这种写法很奇怪，一般也不应该怎么写就是了）：&lt;br /&gt;
select &lt;span style=&quot;color: red;&quot;&gt;/*+ full(@SEL$49A70C8F l) */ &lt;/span&gt;* from employees where department_id in&lt;br /&gt;
(select &lt;span style=&quot;color: red;&quot;&gt;/*+ qb_name(inner) */&lt;/span&gt; department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;);&lt;/p&gt;
&lt;p&gt;&amp;#8211;如前所述，这里/*+ qb_name(inner) */还是需要的，否则转化后的query block名字又会不一样。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: blue;&quot;&gt;如果说能从这里例子总结点什么出来的话，就是如果你在oracle里写SQL，并估计以后可能需要给它加Hint，为了使用Hint方便，可以考虑尽量使用oracle的语法. &lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: blue;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;</content><thr:total>0</thr:total><description>原帖见：&lt;a href=&quot;http://www.itpub.net/viewthread.php?tid=1265917&amp;#38;extra=&amp;#38;page=1&quot; target=&quot;_blank&quot;&gt;http://www.itpub.net/viewthread.php?tid=1265917&amp;#38;extra=&amp;#38;page=1&lt;/a&gt;
关于hint
前几天看看坛子上有人问关于hint的问题，加了hint到底能不能保证执行计划？应不应该用hint？等等。
所以我想写一点关于Hint的小介[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/02/hint'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794219/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/02/hint&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794219/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794219/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;原帖见：&lt;a href=&quot;http://www.itpub.net/viewthread.php?tid=1265917&amp;amp;extra=&amp;amp;page=1&quot; target=&quot;_blank&quot;&gt;http://www.itpub.net/viewthread.php?tid=1265917&amp;amp;extra=&amp;amp;page=1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;关于hint&lt;/p&gt;
&lt;p&gt;前几天看看坛子上有人问关于hint的问题，加了hint到底能不能保证执行计划？应不应该用hint？等等。&lt;/p&gt;
&lt;p&gt;所以我想写一点关于Hint的小介绍， 好久不来itpub了，算抛块砖吧，希望把玉引出来。。。。。。也可以拍砖。&lt;/p&gt;
&lt;p&gt;oracle的hint是人人知道的啦，那加了hint到底能不能保证执行计划？我的看法是能保证，但前提是你用的对。&lt;br /&gt;
到底应不应该用？这个要看具体情况，看是什么样的系统，当然我在自己做测试的时候用Hint是用的很多的。&lt;/p&gt;
&lt;p&gt;下面关于Hint浅议几个话题：&lt;/p&gt;
&lt;p&gt;1，首先Hint是怎么工作的。&lt;/p&gt;
&lt;p&gt;我先跑个简单的SQL，&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;alter system flush shared_pool;&lt;br /&gt;
alter session set events &amp;#8216;10053 trace name context forever, level 1&amp;#8242;;&lt;/p&gt;
&lt;p&gt;select e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这个是执行计划：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation                      | Name             | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT               |                  |       |       |     3 |           |&lt;br /&gt;
| 1   |  TABLE ACCESS BY INDEX ROWID   | EMPLOYEES        |    10 |   110 |     1 |  00:00:01 |&lt;br /&gt;
| 2   |   NESTED LOOPS                 |                  |    10 |   270 |     3 |  00:00:01 |&lt;br /&gt;
| 3   |    TABLE ACCESS BY INDEX ROWID | DEPARTMENTS      |     1 |    16 |     2 |  00:00:01 |&lt;br /&gt;
| 4   |     INDEX RANGE SCAN           | DEPART_NAME_IND  |     1 |       |     1 |  00:00:01 |&lt;br /&gt;
| 5   |    INDEX RANGE SCAN            | EMP_DEPARTMENT_IX|    10 |       |     0 |           |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
Predicate Information:&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
4 &amp;#8211; access(&amp;#8220;D&amp;#8221;.&amp;#8221;DEPARTMENT_NAME&amp;#8221;=:SYS_B_0)&lt;br /&gt;
5 &amp;#8211; access(&amp;#8220;E&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221;=&amp;#8221;D&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221;&lt;img src=&quot;http://www.itpub.net/images/smilies/23.gif&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;然后看它的10053 trace，从trace里面可以清楚的看到在访问departments这个表的问题上，oracle对比了全表扫描和索引range scan,&lt;br /&gt;
最后觉得使用索引DEPART_NAME_IND是最好的。&lt;/p&gt;
&lt;p&gt;SINGLE TABLE ACCESS PATH&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
BEGIN Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
Column (#2): DEPARTMENT_NAME(VARCHAR2)&lt;br /&gt;
AvgLen: 12.00 NDV: 27 Nulls: 0 Density: 0.037037&lt;br /&gt;
Table: DEPARTMENTS  Alias: D&lt;br /&gt;
Card: Original: 27  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
END   Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Access Path: TableScan&lt;/span&gt;&lt;br /&gt;
Cost:  3.01  Resp: 3.01  Degree: 0&lt;br /&gt;
Cost_io: 3.00  Cost_cpu: 41547&lt;br /&gt;
Resp_io: 3.00  Resp_cpu: 41547&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Access Path: index (AllEqRange)&lt;/span&gt;&lt;br /&gt;
Index: DEPART_NAME_IND&lt;br /&gt;
resc_io: 2.00  resc_cpu: 14613&lt;br /&gt;
ix_sel: 0.037037  ix_sel_with_filters: 0.037037&lt;br /&gt;
Cost: 2.00  Resp: 2.00  Degree: 1&lt;br /&gt;
******** Begin index join costing ********&lt;br /&gt;
****** trying bitmap/domain indexes ******&lt;br /&gt;
Access Path: index (AllEqRange)&lt;br /&gt;
Index: DEPART_NAME_IND&lt;br /&gt;
resc_io: 1.00  resc_cpu: 7321&lt;br /&gt;
ix_sel: 0.037037  ix_sel_with_filters: 0.037037&lt;br /&gt;
Cost: 1.00  Resp: 1.00  Degree: 0&lt;br /&gt;
****** finished trying bitmap/domain indexes ******&lt;br /&gt;
Access Path: index (FullScan)&lt;br /&gt;
Index: DEPT_ID_PK&lt;br /&gt;
resc_io: 1.00  resc_cpu: 12521&lt;br /&gt;
ix_sel: 1  ix_sel_with_filters: 1&lt;br /&gt;
Cost: 1.00  Resp: 1.00  Degree: 0&lt;br /&gt;
******** Cost index join ********&lt;br /&gt;
Index join: Considering index join to index DEPART_NAME_IND&lt;br /&gt;
Index join: Joining index DEPT_ID_PK&lt;br /&gt;
Ix HA Join&lt;br /&gt;
Outer table:&lt;br /&gt;
resc: 1.00  card 1.00  bytes: 22  deg: 1  resp: 1.00&lt;br /&gt;
Inner table: &amp;lt;no name&amp;gt;&lt;br /&gt;
resc: 1.25  card: 27.00  bytes: 14  deg: 1  resp: 1.25&lt;br /&gt;
using dmeth: 2  #groups: 1&lt;br /&gt;
Cost per ptn: 0.50  #ptns: 1&lt;br /&gt;
hash_area: 0 (max=0)   Hash join: Resc: 2.75  Resp: 2.75  [multiMatchCost=0.00]&lt;br /&gt;
******** Index join cost ********&lt;br /&gt;
Cost: 2.75&lt;br /&gt;
******** End index join costing ********&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;Best:: AccessPath: IndexRange  Index: DEPART_NAME_IND&lt;br /&gt;
Cost: 2.00  Degree: 1  Resp: 2.00  Card: 1.00  Bytes: 0&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;好，现在我想走departments的全表扫描，很简单，加个full(d)的Hint：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;alter system flush shared_pool;&lt;br /&gt;
alter session set events &amp;#8216;10053 trace name context forever, level 1&amp;#8242;;&lt;/p&gt;
&lt;p&gt;select /*+ full(d) */ e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;执行计划改成了全表扫描：&lt;br /&gt;
============&lt;br /&gt;
Plan Table&lt;br /&gt;
============&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation                    | Name             | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT             |                  |       |       |     4 |           |&lt;br /&gt;
| 1   |  TABLE ACCESS BY INDEX ROWID | EMPLOYEES        |    10 |   110 |     1 |  00:00:01 |&lt;br /&gt;
| 2   |   NESTED LOOPS               |                  |    10 |   270 |     4 |  00:00:01 |&lt;br /&gt;
| 3   |    TABLE ACCESS FULL         | DEPARTMENTS      |     1 |    16 |     3 |  00:00:01 |&lt;br /&gt;
| 4   |    INDEX RANGE SCAN          | EMP_DEPARTMENT_IX|    10 |       |     0 |           |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;然后我们看看10053 trace，我们会看到这时候trace里只能看到关于TableScan的cost计算：&lt;br /&gt;
SINGLE TABLE ACCESS PATH&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
BEGIN Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
Column (#2): DEPARTMENT_NAME(VARCHAR2)&lt;br /&gt;
AvgLen: 12.00 NDV: 27 Nulls: 0 Density: 0.037037&lt;br /&gt;
Table: DEPARTMENTS  Alias: D&lt;br /&gt;
Card: Original: 27  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
END   Single Table Cardinality Estimation&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt; Access Path: TableScan&lt;/span&gt;&lt;br /&gt;
Cost:  3.01  Resp: 3.01  Degree: 0&lt;br /&gt;
Cost_io: 3.00  Cost_cpu: 41547&lt;br /&gt;
Resp_io: 3.00  Resp_cpu: 41547&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt; Best:: AccessPath: TableScan&lt;/span&gt;&lt;br /&gt;
Cost: 3.01  Degree: 1  Resp: 3.01  Card: 1.00  Bytes: 0&lt;/p&gt;
&lt;p&gt;默认情况下，只要一个SQL的所有的可能的access path和join path不是特别多，oracle的query optimizer都会考虑所有的可能的计划，进行比较，得出最佳方案。这是query optimizer的基本功能之一，我们都知道。。。&lt;br /&gt;
而hint的作用就是要求query optimizer在考虑的过程中只考虑某些access或Join path，或者排除某些access或Join path。所以简单的说，&lt;span style=&quot;color: blue;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;HINT的工作方式就是给oracle加限制。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;（只不过有些Hint对oracle加的限制不像限制它智能full table scan这样的直观，比如修改参数用的OPT_PARAM，修改统计信息估计的CARDINALITY， 控制是把子查询数据放在内存还是放在临时空间的MATERIALIZE，等等，不过都是给oracle加人为的限制。）&lt;/p&gt;
&lt;p&gt;这种工作模式在我看来还是比较科学的，只要是合理的使用了hint, 应该是可以保证执行计划按照我们想要的方式走的。&lt;br /&gt;
（但是要想合理的使用Hint还是需要点练习的 &lt;img src=&quot;http://www.itpub.net/images/smilies/14.gif&quot; border=&quot;0&quot; alt=&quot;&quot; /&gt; )&lt;/p&gt;
&lt;p&gt;到这里，让我们考虑一下一个经常被讨论的问题：到底该不该在系统里使用Hint？&lt;br /&gt;
我个人的观点是，&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span style=&quot;color: blue;&quot;&gt;把hint作为最后的手段&lt;/span&gt;&lt;/span&gt;，只要我能通过其他方式把问题解决， 一般我不会考虑使用Hint。（这里的其他方式比如改表的结构，改sql，改统计信息收集的策略。。。），&lt;/p&gt;
&lt;p&gt;对我来说，短期来说Hint也许是个解决问题的最快方案，但它从长远来看会引入风险。&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;因为我没法保证以后数据分布情况不会变化，&lt;br /&gt;
我也没法保证以后表结构不会变化，&lt;br /&gt;
我也没法保证以后数据库不会升级。&lt;/span&gt;&lt;br /&gt;
而以上这些情况都会导致加了Hint的SQL性能变差，而每一种这种变差，都有可能变成业务级别的故障。&lt;br /&gt;
（遥想当年，我也是在很多系统加了很多hint滴，为这些系统默哀一下。。。）&lt;/p&gt;
&lt;p&gt;但这个问题是因系统而异的，比如在线事务系统一般是很少用Hint的，因为SQL一般都比较简单，oracle自己就可以处理的很好。&lt;br /&gt;
但是数据仓库类型的系统可能用hint就会都一些，我以前在ETL的语句里就加过不少，原因很简单，这里的表好多好大，SQL都好长好复杂，优化好难好挑战，我加了Hint可能会为将来引入风险，但是我不加的话估计连现在都保不住。&lt;/p&gt;
&lt;p&gt;从心理的角度分析，我觉得（我就是觉得哈，我不是心理专家)，&lt;br /&gt;
1） 倾向于加hint的人在精神深层次里存在一种对oracle的不信任，&lt;br /&gt;
2） 不倾向于加hint的人在精神深层次里存在一种对oracle的信任，&lt;br /&gt;
（我本人就经历过从最开始的对oracle的盲目信任，到对oracle的盲目不信任，再到对oracle的针对性不信任，再到对oracle的针对性信任。。。）&lt;br /&gt;
我想信任也好，不信任也好，不过是个个人风格问题，当一个人在这个工作里混了5，6，7，8年以后，总会对oracle方面的工作或多或少产生点方法论，世界观之类的东西，&lt;br /&gt;
有的人信任oracle多点，有的人不信任多点，这纯粹是个风格问题，无所谓对错。回到用不用Hint这个话题，这里也存在一个风格的问题。&lt;br /&gt;
不喜欢加Hint的人，像我，就会找一堆不加的好处。喜欢加hint的人可能就会找出一堆加的好处。&lt;/p&gt;
&lt;p&gt;这就像你去做领导，&lt;br /&gt;
1）有的领导是喜欢给team members定好一个完整的流程，什么都要严格的按流程来，对做事的每一个细节都要监控到。&lt;br /&gt;
2）有的领导是喜欢定个high level的目标和规定，然后让team member放手去做。&lt;br /&gt;
这也纯粹是个公司的或个人的风格问题.&lt;br /&gt;
&lt;span style=&quot;color: navy;&quot;&gt;&lt;br /&gt;
对oracle的管理也像治家，治公司，治国，风格或有不同，实在说不上什么是一定好，什么是一定不好的。每个人都可以形成自己的方法论，每个人到了一定阶段都会形成自己的方法论，因人而因，因地制宜，运用之道，存乎一心。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;继续，&lt;br /&gt;
前面看到hint的工作方式还是很科学的，但平时自己加的Hint总是不起作用，这一般都是hint用错了。&lt;/p&gt;
&lt;p&gt;例如这个例子：&lt;/p&gt;
&lt;p&gt;select e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;Here is the plan:&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation                      | Name             | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT               |                  |       |       |     3 |           |&lt;br /&gt;
| 1   |  TABLE ACCESS BY INDEX ROWID   | EMPLOYEES        |    10 |   110 |     1 |  00:00:01 |&lt;br /&gt;
| 2   |   NESTED LOOPS                 |                  |    10 |   270 |     3 |  00:00:01 |&lt;br /&gt;
| 3   |    TABLE ACCESS BY INDEX ROWID | DEPARTMENTS      |     1 |    16 |     2 |  00:00:01 |&lt;br /&gt;
| 4   |    &lt;span style=&quot;color: blue;&quot;&gt; INDEX RANGE SCAN           | DEPART_NAME_IND&lt;/span&gt; |     1 |       |     1 |  00:00:01 |&lt;br /&gt;
| 5   |    INDEX RANGE SCAN            | EMP_DEPARTMENT_IX|    10 |       |     0 |           |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;/p&gt;
&lt;p&gt;对于DEPART_NAME_IND这个索引, 如果我不想让它走range scan，让它走fast full index scan，行不行？&lt;br /&gt;
那我试着加INDEX_FFS这个Hint：&lt;br /&gt;
select&lt;span style=&quot;color: blue;&quot;&gt; /*+ INDEX_FFS(D (&amp;#8220;DEPARTMENTS&amp;#8221;.&amp;#8221;DEPARTMENT_NAME&amp;#8221;)) */ &lt;/span&gt;e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation                     | Name              | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT              |                   |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID  | EMPLOYEES         |    10 |   110 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                |                   |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   3 |    TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |     1 |    16 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  4 |     &lt;span style=&quot;color: blue;&quot;&gt;INDEX RANGE SCAN          | DEPART_NAME_IND &lt;/span&gt; |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |    INDEX RANGE SCAN           | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;结果没有作用，按理说这么简单的语句加Hint是很少不生效的，问题就在于对fast full index scan的理解，&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;fast full index scan这种access path只能用在当你能够从index上取得所有需要的信息，而不需要访问表的时候&lt;/span&gt;，而这里最后很定是&lt;br /&gt;
需要访问DEPARTMENTS的，所以oracle优化器在考虑所有可能的执行计划的时候，完全就不会考虑到fast full index scan。&lt;br /&gt;
就好比oracle考虑的是a, b, c, d，而你要求的是e, 这样的Hint是不会生效的，你只能在a, b, c, d里面选。&lt;/p&gt;
&lt;p&gt;当然如果我们建个复合索引，fast full index scan就没问题了。&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;SQL&amp;gt; create index depart_name_id_ind on departments(department_id, department_name);&lt;/p&gt;
&lt;p&gt;索引已创建。&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; exec dbms_stats.gather_table_stats(user,&amp;#8217;DEPARTMENTS&amp;#8217;);&lt;/p&gt;
&lt;p&gt;PL/SQL 过程已成功完成。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;select &lt;span style=&quot;color: blue;&quot;&gt;/*+ INDEX_FFS(D (&amp;#8220;DEPARTMENTS&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221; &amp;#8220;DEPARTMENTS&amp;#8221;.&amp;#8221;DEPARTMENT_NAME&amp;#8221;)) */ &lt;/span&gt;e.last_name, d.department_name&lt;br /&gt;
from employees e, departments d&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;;&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 3172774359&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
| Id  | Operation                   | Name               | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
|   0 | SELECT STATEMENT            |                    |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES          |    10 |   110 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS              |                    |    10 |   270 |     3   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |    &lt;span style=&quot;color: blue;&quot;&gt;INDEX FAST FULL SCAN     | DEPART_NAME_ID_IND&lt;/span&gt; |     1 |    16 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  4 |    INDEX RANGE SCAN         | EMP_DEPARTMENT_IX  |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;/p&gt;
&lt;p&gt;前面的例子说明使用hint需要多执行计划有一定的了解，但其实很多时候Hint不生效都是因为一些很简单的原因：用错了语法或者用错的地方：&lt;br /&gt;
hint的基本使用方法可以在oracle的sql reference里面看到：&lt;br /&gt;
&lt;a href=&quot;http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/sql_elements006.htm#i35922&quot; target=&quot;_blank&quot;&gt;http://download.oracle.com/docs/ &amp;#8230; ments006.htm#i35922&lt;/a&gt;&lt;br /&gt;
这里也有oracle documented hint的列表，是个不错的参考的地方。&lt;/p&gt;
&lt;p&gt;PS: 如果要看undocumented的oracle hint，这里还不错：&lt;br /&gt;
&lt;a href=&quot;http://www.psoug.org/reference/hints.html&quot; target=&quot;_blank&quot;&gt;http://www.psoug.org/reference/hints.html&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;比较容易让人忽视的一点是要留意Hint的作用域，Hint一般都是在它所在的query block生效，所以如下的Hint是无效的：&lt;br /&gt;
select /*+ full(d) */ * from employees e where department_id in&lt;br /&gt;
(select department_id from departments d where d.department_name=&amp;#8217;IT&amp;#8217;);&lt;/p&gt;
&lt;p&gt;正确的用法是：&lt;br /&gt;
在departments所在的query block加hint&lt;br /&gt;
select * from employees e where department_id in&lt;br /&gt;
(select /*+ full(d) */ department_id from departments d where d.department_name=&amp;#8217;IT&amp;#8217;);&lt;/p&gt;
&lt;p&gt;或者定义query block的名字，然后再外围query block使用query block的名字。&lt;br /&gt;
select /*+ full(@qb1 d) */ * from employees e where department_id in&lt;br /&gt;
(select /*+ qb_name (qb1) */ department_id from departments d where d.department_name=&amp;#8217;IT&amp;#8217;);&lt;/p&gt;
&lt;p&gt;介绍一些&lt;strong&gt;&lt;span style=&quot;font-size: small;&quot;&gt;次常用&lt;/span&gt;&lt;/strong&gt;的hint，&lt;br /&gt;
我们都熟悉那些常用的Hint，&lt;br /&gt;
比如用来调整access path的 （如full, index, parallel&amp;#8230;)，&lt;br /&gt;
调整join order的 （如order, leading&amp;#8230;),&lt;br /&gt;
调整join path的（use_nl, use_hash&amp;#8230;)&lt;br /&gt;
调整remote access的 （如driving_site)，&lt;br /&gt;
调整查询转化的（如rewrite, unnest, merge),&lt;/p&gt;
&lt;p&gt;这些都是比较常用的，说起来没什么意思，现在说几个&amp;#8221;次常用&amp;#8221;的hint.&lt;/p&gt;
&lt;p&gt;1）&lt;strong&gt;&lt;span style=&quot;font-size: small;&quot;&gt;dynamic_sampling,&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;
这个Hint在sql reference里面有介绍：&lt;br /&gt;
The DYNAMIC_SAMPLING hint instructs the optimizer how to control dynamic sampling to improve server performance by determining more accurate predicate selectivity and statistics for tables and indexes.&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;drop table t1;&lt;br /&gt;
drop table t2;&lt;br /&gt;
create table t1 (x int, y int);&lt;br /&gt;
create index t1_xy on t1(x,y);&lt;/p&gt;
&lt;p&gt;create table t2 (x int);&lt;br /&gt;
create index t2_x on t2(x);&lt;/p&gt;
&lt;p&gt;insert into t1 select mod(rownum, 10), mod(rownum, 10) from dba_objects where rownum&amp;lt;=50000;&lt;br /&gt;
insert into t2 select mod(rownum, 50) from dba_objects where rownum&amp;lt;=50000;&lt;/p&gt;
&lt;p&gt;commit;&lt;/p&gt;
&lt;p&gt;exec dbms_stats.gather_table_stats(user,&amp;#8217;T1&amp;#8242;);&lt;br /&gt;
exec dbms_stats.gather_table_stats(user,&amp;#8217;T2&amp;#8242;);&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; set autotrace traceonly exp&lt;br /&gt;
SQL&amp;gt; select t1.x, t2.x from t1,t2&lt;br /&gt;
2  where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 4152676900&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT  |       |   501K|  3428K|    32  (29)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN        |       |   501K|  3428K|    32  (29)| 00:00:01 |&lt;br /&gt;
|*  2 |   INDEX RANGE SCAN| T1_XY |   496 |  2480 |    19   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |   INDEX RANGE SCAN| T2_X  |  1011 |  2022 |     4   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;Predicate Information (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=&amp;#8221;T1&amp;#8243;.&amp;#8221;X&amp;#8221;)&lt;br /&gt;
2 &amp;#8211; access(&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221;=1 AND &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;=1)&lt;br /&gt;
3 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=1)&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; select &lt;span style=&quot;color: red;&quot;&gt;/*+ dynamic_sampling(4) */&lt;/span&gt; t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 224376697&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT  |       |  5015K|    33M|   110  (80)| 00:00:02 |&lt;br /&gt;
|*  1 |  HASH JOIN        |       |  5015K|    33M|   110  (80)| 00:00:02 |&lt;br /&gt;
|*  2 |   INDEX RANGE SCAN| T2_X  |  1011 |  2022 |     4   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |   INDEX RANGE SCAN| T1_XY |  4963 | 24815 |    19   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;Predicate Information (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=&amp;#8221;T1&amp;#8243;.&amp;#8221;X&amp;#8221;)&lt;br /&gt;
2 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=1)&lt;br /&gt;
3 &amp;#8211; access(&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221;=1 AND &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;=1)&lt;/p&gt;
&lt;p&gt;Note&lt;br /&gt;
&amp;#8212;&amp;#8211;&lt;br /&gt;
- dynamic sampling used for this statement&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;那个执行计划更好一些？应该是第二个，&lt;/p&gt;
&lt;p&gt;这里的第一个执行计划把t1作为驱动表，t2作为被驱动表，因为oracle认为t1.x=1 and t1.y=1应该返回更少的行数。&lt;br /&gt;
oracle在判断t1.x=1 and t1.y=1的总行数 =&amp;gt; （t1.x=1的选择率 * t1.y=1的选择率）* t1行数 =&amp;gt; （0.1 * 0.1）* 50000 = 500 （计划里是496）&lt;br /&gt;
oracle在判断t2.x=1的总行数 =&amp;gt; t2.x=1的选择率 * t2行数 =&amp;gt; 0.02 * 50000 = 1000.&lt;/p&gt;
&lt;p&gt;所以oracle把t1作为驱动表是可以理解的，但问题是实际的数据分布t1.x总是等于t1.y，所以真实的数据t1.x=1 and t1.y=1的总行数 = t1.x=1的选择率 * t1行数 = 0.1 * 50000 = 5000 （计划里的4963) !&lt;/p&gt;
&lt;p&gt;为了让oracle认识到这一点，我们使用level 4的dynamic_sampling, dynamic_sampling level 4的意思是：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;Level 4: Apply dynamic sampling to all tables that meet Level 3 criteria, plus all&lt;br /&gt;
tables that have single-table predicates that reference 2 or more columns. The&lt;br /&gt;
number of blocks sampled is the default number of dynamic sampling blocks. For&lt;br /&gt;
unanalyzed tables, the number of blocks sampled is two times the default number&lt;br /&gt;
of dynamic sampling blocks&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;从level 4开始oracle开始对“tables that have single-table predicates that reference 2 or more columns” 这种情况开始采样，所以能够意识到真实的数据分布是什么样，所以我们&lt;br /&gt;
看到第二个是以t2为驱动表的。&lt;/p&gt;
&lt;p&gt;这种类似的问题在复杂的SQL里面会很常见。&lt;/p&gt;
&lt;p&gt;但是dynamic_sampling这个Hint会在oracle解析的时候产生额外的开销，我很少真的在代码里用，不过我经常在调优的时候用。&lt;br /&gt;
比如当我运行完这个SQL语句之后：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;select /*+ dynamic_sampling(4) */ t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;我会马上跟一个：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;select * from table(dbms_xplan.display_cursor(null, 0 , &amp;#8216;advanced&amp;#8217;));&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这样就可以得到为了实现这个比较好的计划所需要的所有的Hint，你如果要在系统里加hint, 动态采样+dbms_xplan.display_cursor是个捷径:&lt;/p&gt;
&lt;p&gt;/*+&lt;br /&gt;
BEGIN_OUTLINE_DATA&lt;br /&gt;
IGNORE_OPTIM_EMBEDDED_HINTS&lt;br /&gt;
OPTIMIZER_FEATURES_ENABLE(&amp;#8216;10.2.0.1&amp;#8242;)&lt;br /&gt;
ALL_ROWS&lt;br /&gt;
OUTLINE_LEAF(@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;))&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221; &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;))&lt;br /&gt;
LEADING(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
USE_HASH(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
END_OUTLINE_DATA&lt;br /&gt;
*/&lt;/p&gt;
&lt;p&gt;在真实使用的时候你必须把outline相关的和IGNORE_OPTIM_EMBEDDED_HINTS这个奇怪的Hint去掉，&lt;br /&gt;
也可以把OPTIMIZER_FEATURES_ENABLE(&amp;#8216;10.2.0.1&amp;#8242;)，ALL_ROWS去掉，因为这些环境不大会改变。&lt;/p&gt;
&lt;p&gt;然后可以把oracle自定义的query block去掉，如果你的sql有多个query block的话可能需要自己定义query block的名字（见我前面的帖子）&lt;/p&gt;
&lt;p&gt;我这个SQL最后留下这么几个hint就够了：&lt;br /&gt;
/*+&lt;br /&gt;
INDEX(&amp;#8220;T2&amp;#8243; (&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;))&lt;br /&gt;
INDEX(&amp;#8220;T1&amp;#8243; (&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221; &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;))&lt;br /&gt;
LEADING( &amp;#8220;T2&amp;#8243; &amp;#8220;T1&amp;#8243;)&lt;br /&gt;
USE_HASH(&amp;#8220;T1&amp;#8243;)&lt;br /&gt;
*/&lt;/p&gt;
&lt;p&gt;还有一个问题，就是有的SQL一跑就是几天，甚至会影响整个系统，你优化的时候不可能把它跑一遍，所以也不能用dbms_xplan.display_cursor，那你可以考虑这个方法。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;alter session set events &amp;#8216;10132 trace name context forever, level 1&amp;#8242;;&lt;/span&gt;&lt;br /&gt;
这里使用10053效果也类似，但我发现10053只有在hard parse的时候才生成trace，所以一般用10053之前可能需要flush shared_pool。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;set autotrace traceonly exp&lt;br /&gt;
select /*+ dynamic_sampling(4) */ t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;于是在trace里你可以看到下面的内容：&lt;br /&gt;
sql_id=62dhqxdq49t6a.&lt;br /&gt;
Current SQL statement for this session:&lt;br /&gt;
EXPLAIN PLAN SET STATEMENT_ID=&amp;#8217;PLUS1777&amp;#8242; FOR select /*+ dynamic_sampling(4) */ t1.x, t2.x from t1,t2&lt;br /&gt;
where t1.x=1 and t1.y=1 and t2.x=t1.x&lt;/p&gt;
&lt;p&gt;============&lt;br /&gt;
Plan Table&lt;br /&gt;
============&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| Id  | Operation          | Name    | Rows  | Bytes | Cost  | Time      |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
| 0   | SELECT STATEMENT   |         |       |       |   110 |           |&lt;br /&gt;
| 1   |  HASH JOIN         |         | 4897K |   33M |   110 |  00:00:02 |&lt;br /&gt;
| 2   |   INDEX RANGE SCAN | T2_X    |  1011 |  2022 |     4 |  00:00:01 |&lt;br /&gt;
| 3   |   INDEX RANGE SCAN | T1_XY   |  4963 |   24K |    19 |  00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-+&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;+&lt;br /&gt;
Predicate Information:&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=&amp;#8221;T1&amp;#8243;.&amp;#8221;X&amp;#8221;)&lt;br /&gt;
2 &amp;#8211; access(&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;=1)&lt;br /&gt;
3 &amp;#8211; access(&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221;=1 AND &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;=1)&lt;/p&gt;
&lt;p&gt;Content of other_xml column&lt;br /&gt;
===========================&lt;br /&gt;
db_version     : 10.2.0.1&lt;br /&gt;
parse_schema   : HR&lt;br /&gt;
dynamic_sampling: yes&lt;br /&gt;
plan_hash      : 224376697&lt;br /&gt;
Outline Data:&lt;br /&gt;
/*+&lt;br /&gt;
BEGIN_OUTLINE_DATA&lt;br /&gt;
IGNORE_OPTIM_EMBEDDED_HINTS&lt;br /&gt;
OPTIMIZER_FEATURES_ENABLE(&amp;#8216;10.2.0.1&amp;#8242;)&lt;br /&gt;
ALL_ROWS&lt;br /&gt;
OUTLINE_LEAF(@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T2&amp;#8243;.&amp;#8221;X&amp;#8221;))&lt;br /&gt;
INDEX(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; (&amp;#8220;T1&amp;#8243;.&amp;#8221;X&amp;#8221; &amp;#8220;T1&amp;#8243;.&amp;#8221;Y&amp;#8221;))&lt;br /&gt;
LEADING(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T2&amp;#8243;@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
USE_HASH(@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;T1&amp;#8243;@&amp;#8221;SEL$1&amp;#8243;)&lt;br /&gt;
END_OUTLINE_DATA&lt;br /&gt;
*/&lt;/p&gt;
&lt;p&gt;关于这个Hint: &lt;span style=&quot;color: blue;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;swap_join_inputs&lt;/span&gt;&lt;/span&gt;,&lt;br /&gt;
这是一个undocumented Hint,在官方文档里面看不到，它的作用是帮我们调整join的顺序。&lt;br /&gt;
一般调整Join的顺序用leading或者order就可以了，但是看看下面的4表连接例子：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;select e.last_name, d.department_name, j.job_title&lt;br /&gt;
from employees e, departments d, jobs j, locations l&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and e.job_id = j.job_id&lt;br /&gt;
and d.location_id=l.location_id&lt;br /&gt;
and j.job_title=&amp;#8217;Programmer&amp;#8217;&lt;br /&gt;
and l.city=&amp;#8217;Beijing&amp;#8217;&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;&lt;br /&gt;
;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 3164695383&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
| Id  | Operation                      | Name              | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
|   0 | SELECT STATEMENT               |                   |     1 |    78 |     5   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  NESTED LOOPS                  |                   |     1 |    78 |     5   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                 |                   |    10 |   510 |     4   (0)| 00:00:01 |&lt;br /&gt;
|   3 |    NESTED LOOPS                |                   |     1 |    31 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   4 |     TABLE ACCESS BY INDEX ROWID| DEPARTMENTS       |     1 |    19 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |      INDEX RANGE SCAN          | DEPART_NAME_IND   |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  6 |     TABLE ACCESS BY INDEX ROWID| LOCATIONS         |     1 |    12 |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  7 |      INDEX RANGE SCAN          | LOC_CITY_IX       |     1 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
|   8 |    TABLE ACCESS BY INDEX ROWID | EMPLOYEES         |    10 |   200 |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  9 |     INDEX RANGE SCAN           | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
|* 10 |   TABLE ACCESS BY INDEX ROWID  | JOBS              |     1 |    27 |     1   (0)| 00:00:01 |&lt;br /&gt;
|* 11 |    INDEX UNIQUE SCAN           | JOB_ID_PK         |     1 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这里的连接顺序是&lt;br /&gt;
1） departments先和location连，departments作为驱动表。&lt;br /&gt;
2） 上一步的结果集和employees连， 上一步的结果集作为驱动表。&lt;br /&gt;
3） 上一步的结果集和JOBS连， 上一步的结果集作为驱动表。&lt;/p&gt;
&lt;p&gt;这里有oracle的一个规则，就是如果前面一步的Join的结果在和其他表做连接，那么默认情况下总是把前面一步的Join的结果作为驱动者，&lt;/p&gt;
&lt;p&gt;CBO本身一般不会基于cost的考虑来打破这个规则，所以如果我想要的连接顺序变成下面这样，似乎有点麻烦，因为leading 和order这样的Hint是做不到的：&lt;br /&gt;
1） departments先和location连，departments作为驱动表。&lt;br /&gt;
2） 上一步的结果集和employees连， employees作为驱动表。&lt;br /&gt;
3） 上一步的结果集和JOBS连， JOBS作为驱动表。&lt;/p&gt;
&lt;p&gt;你可以试一下swap_join_inputs这个Hint，swap_join_inputs就是用来修改上面说的这个规则的：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;select&lt;br /&gt;
/*+ leading(d l e j)&lt;br /&gt;
use_nl(l)&lt;br /&gt;
use_hash(e)&lt;br /&gt;
swap_join_inputs(e)&lt;br /&gt;
use_hash(j)&lt;br /&gt;
swap_join_inputs(j)&lt;br /&gt;
*/&lt;br /&gt;
e.last_name, d.department_name, j.job_title&lt;br /&gt;
from employees e, departments d, jobs j, locations l&lt;br /&gt;
where e.department_id=d.department_id&lt;br /&gt;
and e.job_id = j.job_id&lt;br /&gt;
and d.location_id=l.location_id&lt;br /&gt;
and j.job_title=&amp;#8217;Programmer&amp;#8217;&lt;br /&gt;
and l.city=&amp;#8217;Beijing&amp;#8217;&lt;br /&gt;
and d.department_name=&amp;#8217;IT&amp;#8217;&lt;br /&gt;
;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation                       | Name            | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT                |                 |     1 |    78 |    10  (10)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN                      |                 |     1 |    78 |    10  (10)| 00:00:01 |&lt;br /&gt;
|*  2 |   TABLE ACCESS FULL             | JOBS            |     1 |    27 |     3   (0)| 00:00:01 |&lt;br /&gt;
|*  3 |   HASH JOIN                     |                 |    10 |   510 |     7  (15)| 00:00:01 |&lt;br /&gt;
|   4 |    TABLE ACCESS FULL            | EMPLOYEES       |   107 |  2140 |     3   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |    TABLE ACCESS BY INDEX ROWID  | LOCATIONS       |     1 |    12 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   6 |     NESTED LOOPS                |                 |     1 |    31 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   7 |      TABLE ACCESS BY INDEX ROWID| DEPARTMENTS     |     1 |    19 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  8 |       INDEX RANGE SCAN          | DEPART_NAME_IND |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  9 |      INDEX RANGE SCAN           | LOC_CITY_IX     |     1 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;你也许奇怪为什么我要加use_hash(e)这样的Hint，因为我发现如果我使用其他join的方式，swap_join_inputs一般是不生效的。&lt;br /&gt;
由于swap_join_inputs是个没有官方记载的Hint，所以我还不能肯定的说swap_join_inputs只支持hash join, 这一点欢迎大家都来测一下。&lt;/p&gt;
&lt;p&gt;但是如果你想连接顺序变成这样该怎么搞？&lt;br /&gt;
1） departments和location连。&lt;br /&gt;
2） employees和jobs去连接&lt;br /&gt;
3） 第一步的结果和第二步的结果做连接，第二步的结果作为驱动。&lt;/p&gt;
&lt;p&gt;(⊙o⊙)… 别难为我了，写成子查询吧。。。&lt;/p&gt;
&lt;p&gt;SWAP_JOIN_INPUTS这个Hint还可以用在调整外连接的连接顺序，下面这里例子我在wabjtam123 的帖子里贴过的，&lt;/p&gt;
&lt;p&gt;SQL&amp;gt; set autotrace traceonly&lt;br /&gt;
SQL&amp;gt; select&lt;br /&gt;
2  t2.c1, t2.c2&lt;br /&gt;
3  from t1,t2 where t2.c1(+)=t1.c1;&lt;/p&gt;
&lt;p&gt;未选定行&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 1823443478&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT   |      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN OUTER   |      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|   2 |   TABLE ACCESS FULL| T1   |     1 |    13 |     2   (0)| 00:00:01 |&lt;br /&gt;
|   3 |   TABLE ACCESS FULL| T2   |     1 |    26 |     2   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;要调整outer join的连接顺序，使用leading是不够的，oracle在处理outer join的连接顺序的时候会有些小固执，需要加上USE_HASH&lt;br /&gt;
和SWAP_JOIN_INPUTS：&lt;/p&gt;
&lt;p&gt;SQL&amp;gt;&lt;br /&gt;
SQL&amp;gt; select&lt;br /&gt;
2  /*+&lt;br /&gt;
3      LEADING(t1 t2)&lt;br /&gt;
4      USE_HASH(t2)&lt;br /&gt;
5      SWAP_JOIN_INPUTS(t2)&lt;br /&gt;
6  */&lt;br /&gt;
7  t2.c1, t2.c2&lt;br /&gt;
8  from t1,t2 where t2.c1(+)=t1.c1;&lt;/p&gt;
&lt;p&gt;未选定行&lt;/p&gt;
&lt;p&gt;执行计划&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
Plan hash value: 312430291&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
| Id  | Operation             | Name | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
|   0 | SELECT STATEMENT      |      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|*  1 |  HASH JOIN RIGHT OUTER|      |     1 |    39 |     5  (20)| 00:00:01 |&lt;br /&gt;
|   2 |   TABLE ACCESS FULL   | T2   |     1 |    26 |     2   (0)| 00:00:01 |&lt;br /&gt;
|   3 |   TABLE ACCESS FULL   | T1   |     1 |    13 |     2   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;font-size: small;&quot;&gt;query block的名字&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这段的实际应用意义不大，研究这个主要为了好玩。&lt;/p&gt;
&lt;p&gt;前面提到我们可以用qb_name这个hint来定义SQL里面的query block的名字，实际上如果我们多看看&lt;br /&gt;
dbms_xplan.display_cursor的advanced模式的输出，或者看看10053 trace，或者看看10132 trace，就能发现其实oracle的CBO会&lt;br /&gt;
自己定义query block的名字，而且你会发现对于固定的SQL，这些query block的名字都是固定的。&lt;/p&gt;
&lt;p&gt;这里打算介绍一下oracle是如何确定这些query block名字的，这已经超出了hint的范畴，但是如果你看到oracle给你列出这样的一条Hint，&lt;br /&gt;
了解query block的命名的由来对你读懂这个hint是有帮助的：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;LEADING(@&amp;#8221;SEL$F5BB74E1&amp;#8243; &amp;#8220;D&amp;#8221;@&amp;#8221;SEL$1&amp;#8243; &amp;#8220;EMPLOYEES&amp;#8221;@&amp;#8221;SEL$2&amp;#8243;) &lt;/span&gt;&lt;br /&gt;
&amp;#8211;如果SQL多次出现employees这张表，你知道这个Hint是指哪个employees么？&lt;/p&gt;
&lt;p&gt;其实一般来说，oracle对query block的命名还是很直观的，&lt;br /&gt;
如果是一个select，那么就命名为SEL$n，这里的n是1，2，3&amp;#8230;&lt;br /&gt;
如果是delete，就命名为DEL$n，是update，就命名为UPD$n，是insert，就叫INS$n, 是merge，就叫MISC$n&amp;#8230;&lt;/p&gt;
&lt;p&gt;下面我举出两个例子，一个select, 一个delete，其他的大家可以自己去试。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: blue;&quot;&gt;explain plan for&lt;br /&gt;
select * from employees where salary = (select max(salary) from employees);&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$1&lt;/span&gt; / EMPLOYEES@SEL$1&lt;br /&gt;
2 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$2&lt;/span&gt;&lt;br /&gt;
3 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$2&lt;/span&gt; / EMPLOYEES@SEL$2&lt;/p&gt;
&lt;p&gt;explain plan for&lt;br /&gt;
delete from employees;&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;br /&gt;
Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;DEL$1&lt;/span&gt;&lt;br /&gt;
2 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;DEL$1&lt;/span&gt; / EMPLOYEES@DEL$1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;那为什么会出现类似于SEL$F5BB74E1这样的query block呢？这是因为oracle做了sql转化，我们知道oracle处于性能考虑会&lt;br /&gt;
把一些子查询转化为表与表连接的模式，SQL转化是个比较有意思的话题，包含的东西也很多（不仅仅针对子查询），&lt;br /&gt;
对于子查询而言，就是当你的SQL包含了子查询或者视图，oracle会对你的SQL进行转化，当然这种转化在10g里是基于cost的，也就是说如果转化后发现cost太高，这个转化就不会被采用。&lt;/p&gt;
&lt;p&gt;对于oracle的SQL转化主要是做：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;1） 转化SPJ (select + project + join) view&lt;br /&gt;
2） unnest Subquery&lt;br /&gt;
3） merge Complex View （mergable complex view的定义可见于oracle performance tuning guide)&lt;br /&gt;
4） Predicate Pushing， or expense, 物化视图重写，等。。。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;那么当转化发生后，SQL的结构就变了，所以oracle会为转化后的SQL生成新的query block，为了和没有发生转化的SQL有所区别，&lt;br /&gt;
oracle在这里采用比较特殊的格式。&lt;/p&gt;
&lt;p&gt;转化后oracle会把原来的一个外围的query block（假如名字是a), 和一个内部的query block(假如名字是b), 转化生成的新的query block的名字应该是a 和 b 的hash函数。&lt;/p&gt;
&lt;p&gt;看看下面的例子：&lt;br /&gt;
SQL1，这是一个多层嵌套，每个嵌套的子查询都可以被转化，我们能看到oracle在做完转化后生成的新的query block为SEL$9C113579。&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb1) */ * from&lt;br /&gt;
(select /*+ qb_name(qb2) */ * from&lt;br /&gt;
(select /*+ qb_name(qb3) */ * from employees));&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$9C113579&lt;/span&gt; / EMPLOYEES@QB3&lt;/p&gt;
&lt;p&gt;SQL2，是SQL1的第二层嵌套的查询，可以看到转化后生成的query block名字是SEL$1B0F72FE&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb2) */ * from&lt;br /&gt;
(select /*+ qb_name(qb3) */ * from employees);&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$1B0F72FE&lt;/span&gt; / EMPLOYEES@QB3&lt;/p&gt;
&lt;p&gt;SQL3，最外面得查询还是叫qb1，在里面随便套了一个子查询，但是我们把第二层查询的名字定义为SEL$1B0F72FE。&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb1) */ * from&lt;br /&gt;
(select /*+ qb_name(SEL$1B0F72FE) */ * from departments);&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$9C113579&lt;/span&gt; / EMPLOYEES@SEL$1B0F72FE&lt;/p&gt;
&lt;p&gt;可以看到转化后的query block的名字是SEL$9C113579，和我们的第一个SQL转化后得到的query block名字一致，这就可以证明，当oracle对SQL的子查询进行了转化后，&lt;br /&gt;
会生成新的query block的名字，这个名字是由原来的外围query block名字和原来的内存query block名字决定的，估计是一个hash 函数。&lt;/p&gt;
&lt;p&gt;如果我们把外面的query block名字改掉，得到的新的转化后的query block名字就会变了：&lt;/p&gt;
&lt;p&gt;explain plan for&lt;br /&gt;
select /*+ qb_name(qbnew) */ * from&lt;br /&gt;
(select /*+ qb_name(SEL$1B0F72FE) */ * from departments);&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$90C23CFB&lt;/span&gt; / DEPARTMENTS@SEL$1B0F72FE  &amp;#8211;变了&lt;/p&gt;
&lt;p&gt;下面这个例子可以看出，我把第二层的子查询做了一些改动，又套上了一些其他的子查询，但是使用no_merge hint来避免里面的子查询被oracle的CBO转化掉：&lt;br /&gt;
explain plan for&lt;br /&gt;
select /*+ qb_name(qb1) */ * from&lt;br /&gt;
(select /*+ qb_name(SEL$1B0F72FE) */ * from employees where department_id in&lt;br /&gt;
(select /*+ no_merge */ max(department_id) from departments where location_id in&lt;br /&gt;
(select /*+ no_merge */ max(location_id) from locations)));&lt;/p&gt;
&lt;p&gt;select * from table(dbms_xplan.display(null,null,&amp;#8217;alias&amp;#8217;));&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; &lt;span style=&quot;color: red;&quot;&gt;SEL$9C113579&lt;/span&gt; / EMPLOYEES@SEL$1B0F72FE&lt;br /&gt;
2 &amp;#8211; SEL$9C113579 / EMPLOYEES@SEL$1B0F72FE&lt;br /&gt;
3 &amp;#8211; SEL$1&lt;br /&gt;
4 &amp;#8211; SEL$1        / DEPARTMENTS@SEL$1&lt;br /&gt;
5 &amp;#8211; SEL$1        / DEPARTMENTS@SEL$1&lt;br /&gt;
6 &amp;#8211; SEL$2&lt;br /&gt;
7 &amp;#8211; SEL$2        / LOCATIONS@SEL$2&lt;/p&gt;
&lt;p&gt;可以看到，即使把内层的SQL做了这么多改变，最终转化出来的query block的名字还叫SEL$9C113579。&lt;/p&gt;
&lt;p&gt;最后看一个特殊的例子：&lt;/p&gt;
&lt;p&gt;这里是一个简单的2个表连接，没有子查询，但是我们可以看到在query block的名字是SEL$58A6D7F6，和我前面说的规则并不一样，为什么会这样？&lt;/p&gt;
&lt;p&gt;explain plan for&lt;br /&gt;
select department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;;&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
| Id  | Operation                     | Name             | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
|   0 | SELECT STATEMENT              |                  |     4 |    76 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID  | DEPARTMENTS      |     4 |    28 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                |                  |     4 |    76 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   3 |    TABLE ACCESS BY INDEX ROWID| LOCATIONS        |     1 |    12 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  4 |     INDEX RANGE SCAN          | LOC_CITY_IX      |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  5 |    INDEX RANGE SCAN           | DEPT_LOCATION_IX |     4 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: red;&quot;&gt; 1 &amp;#8211; SEL$58A6D7F6 / D@SEL$1&lt;br /&gt;
3 &amp;#8211; SEL$58A6D7F6 / L@SEL$1&lt;br /&gt;
4 &amp;#8211; SEL$58A6D7F6 / L@SEL$1&lt;br /&gt;
5 &amp;#8211; SEL$58A6D7F6 / D@SEL$1&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;原因在于这个SQL使用了ANSI的表连接语法，oracle在解析“join locations l on”这样的条件的时候会把它看做是一个子查询，于是乎会做转化，于是乎生成SEL$58A6D7F6这样的query block名字。&lt;/p&gt;
&lt;p&gt;在10053 trace里面会看到(VIEW MERGE SEL$2; SEL$1)这样的字样， 然后query被转化为：&lt;br /&gt;
select department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;&lt;/p&gt;
&lt;p&gt;10053 trace的部分内容：&lt;br /&gt;
&lt;span style=&quot;color: blue;&quot;&gt;SQL:******* UNPARSED QUERY IS *******&lt;br /&gt;
SELECT &amp;#8220;D&amp;#8221;.&amp;#8221;DEPARTMENT_ID&amp;#8221; &amp;#8220;DEPARTMENT_ID&amp;#8221; FROM &amp;#8220;HR&amp;#8221;.&amp;#8221;DEPARTMENTS&amp;#8221; &amp;#8220;D&amp;#8221;,&amp;#8221;HR&amp;#8221;.&amp;#8221;LOCATIONS&amp;#8221; &amp;#8220;L&amp;#8221; WHERE &amp;#8220;L&amp;#8221;.&amp;#8221;CITY&amp;#8221;=&amp;#8217;Beijing&amp;#8217; AND &amp;#8220;D&amp;#8221;.&amp;#8221;LOCATION_ID&amp;#8221;=&amp;#8221;L&amp;#8221;.&amp;#8221;LOCATION_ID&amp;#8221;&lt;br /&gt;
Query block (04B6A5E0) unchanged&lt;br /&gt;
Registered qb: SEL$58A6D7F6 0&amp;#215;4b6a5e0 (&lt;span style=&quot;color: red;&quot;&gt;VIEW MERGE SEL$2; SEL$1&lt;/span&gt;)&lt;br /&gt;
signature (): qb_name=SEL$58A6D7F6 nbfros=2 flg=0&lt;br /&gt;
fro(0): flg=0 objn=51905 hint_alias=&amp;#8221;D&amp;#8221;@&amp;#8221;SEL$1&amp;#8243;&lt;br /&gt;
fro(1): flg=0 objn=51900 hint_alias=&amp;#8221;L&amp;#8221;@&amp;#8221;SEL$1&amp;#8243;&lt;br /&gt;
&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&lt;br /&gt;
&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&amp;#8230;&lt;br /&gt;
****************&lt;br /&gt;
QUERY BLOCK TEXT&lt;br /&gt;
****************&lt;br /&gt;
select department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;这对我们有什么影响吗？ 其实影响不大，我前面也说这一段不是为了使用，仅仅为了好玩，不过假如上面的SQL作为我们下面语句的子查询，并且我想让表locations走全表扫描，我按理应该可以这样写hint：&lt;br /&gt;
explain plan for&lt;br /&gt;
select &lt;span style=&quot;color: red;&quot;&gt;/*+ full(@inner l) */&lt;/span&gt; * from employees where department_id in&lt;br /&gt;
(select &lt;span style=&quot;color: red;&quot;&gt;/*+ qb_name(inner) */&lt;/span&gt; department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;);&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
| Id  | Operation                         | Name              | Rows  | Bytes | Cost (%CPU)| Time     |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;br /&gt;
|   0 | SELECT STATEMENT                  |                   |    39 |  3159 |     6  (17)| 00:00:01 |&lt;br /&gt;
|   1 |  TABLE ACCESS BY INDEX ROWID      | EMPLOYEES         |    10 |   680 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   2 |   NESTED LOOPS                    |                   |    39 |  3159 |     6  (17)| 00:00:01 |&lt;br /&gt;
|   3 |    VIEW                           | VW_NSO_1          |     4 |    52 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   4 |     HASH UNIQUE                   |                   |     4 |    76 |            |          |&lt;br /&gt;
|   5 |      TABLE ACCESS BY INDEX ROWID  | DEPARTMENTS       |     4 |    28 |     1   (0)| 00:00:01 |&lt;br /&gt;
|   6 |       NESTED LOOPS                |                   |     4 |    76 |     3   (0)| 00:00:01 |&lt;br /&gt;
|   7 |        TABLE ACCESS BY INDEX ROWID| LOCATIONS         |     1 |    12 |     2   (0)| 00:00:01 |&lt;br /&gt;
|*  8 |         INDEX RANGE SCAN          | LOC_CITY_IX       |     1 |       |     1   (0)| 00:00:01 |&lt;br /&gt;
|*  9 |        INDEX RANGE SCAN           | DEPT_LOCATION_IX  |     4 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
|* 10 |    INDEX RANGE SCAN               | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;Query Block Name / Object Alias (identified by operation id):&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;-&lt;/p&gt;
&lt;p&gt;1 &amp;#8211; SEL$78C29F24 / EMPLOYEES@SEL$2&lt;br /&gt;
3 &amp;#8211; SEL$49A70C8F / VW_NSO_1@SEL$78C29F24&lt;br /&gt;
4 &amp;#8211; SEL$49A70C8F&lt;br /&gt;
5 &amp;#8211; SEL$49A70C8F / D@SEL$1&lt;br /&gt;
7 &amp;#8211; SEL$49A70C8F / L@SEL$1&lt;br /&gt;
8 &amp;#8211; SEL$49A70C8F / L@SEL$1&lt;br /&gt;
9 &amp;#8211; SEL$49A70C8F / D@SEL$1&lt;br /&gt;
10 &amp;#8211; SEL$78C29F24 / EMPLOYEES@SEL$2&lt;/p&gt;
&lt;p&gt;但如你所见，hint似乎没有生效，这个原因就是尽管我们给&lt;br /&gt;
(select /*+ qb_name(inner) */ department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;)&lt;br /&gt;
这个子查询定义了query block的名字，但是因为这个是ANSI语法的连接，oracle会做一次转换，这次转化会给子查询生成一个新的query block(SEL$49A70C8F),&lt;br /&gt;
这进一步导致/*+ full(@inner l) */这个针对inner的Hint失效。&lt;/p&gt;
&lt;p&gt;要想达到目的的方法也很简单， 比如hint可以这么写：&lt;br /&gt;
select * from employees where department_id in&lt;br /&gt;
(select&lt;span style=&quot;color: red;&quot;&gt; /*+ full(l) */ &lt;/span&gt;department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;);&lt;/p&gt;
&lt;p&gt;或者既然已经知道了新的query block的名字，我们就可以这么写（当然这种写法很奇怪，一般也不应该怎么写就是了）：&lt;br /&gt;
select &lt;span style=&quot;color: red;&quot;&gt;/*+ full(@SEL$49A70C8F l) */ &lt;/span&gt;* from employees where department_id in&lt;br /&gt;
(select &lt;span style=&quot;color: red;&quot;&gt;/*+ qb_name(inner) */&lt;/span&gt; department_id from departments d join locations l on d.location_id=l.location_id where l.city=&amp;#8217;Beijing&amp;#8217;);&lt;/p&gt;
&lt;p&gt;&amp;#8211;如前所述，这里/*+ qb_name(inner) */还是需要的，否则转化后的query block名字又会不一样。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: blue;&quot;&gt;如果说能从这里例子总结点什么出来的话，就是如果你在oracle里写SQL，并估计以后可能需要给它加Hint，为了使用Hint方便，可以考虑尽量使用oracle的语法. &lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;color: blue;&quot;&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794219/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/02/hint&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794219/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794219/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">Oracle</category><category domain="http://www.dbadoc.com">hint</category><pubDate>Tue, 02 Feb 2010 11:20:17 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2045</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/02/hint</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794219/5445352</fs:itemid></item><item><title>Tuning the Redo log Buffer Cache and Resolving Redo Latch Contention</title><link atom:type="text/html">http://www.dbadoc.com/2010/01/tuning-the-redo-log-buffer-cache-and-resolving-redo-latch-contention</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2042</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/01/tuning-the-redo-log-buffer-cache-and-resolving-redo-latch-contention">&lt;table border=&quot;0&quot; cellspacing=&quot;6&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan=&quot;4&quot; align=&quot;left&quot; valign=&quot;top&quot;&gt;&lt;strong&gt;Tuning the Redolog Buffer Cache and Resolving Redo Latch Contention [ID 147471.1]&lt;/strong&gt;&lt;/td&gt;
&lt;td colspan=&quot;2&quot; valign=&quot;top&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;6&quot; align=&quot;left&quot; valign=&quot;top&quot;&gt;
&lt;hr size=&quot;1&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot; width=&quot;25%&quot; valign=&quot;top&quot;&gt;&lt;/td&gt;
&lt;td colspan=&quot;3&quot; width=&quot;50%&quot; valign=&quot;top&quot;&gt;&lt;em&gt;Modified&lt;/em&gt; 16-JUL-2009     &lt;em&gt;Type&lt;/em&gt; BULLETIN     &lt;em&gt;Status&lt;/em&gt; PUBLISHED&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;Purpose:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;This article provide detailed information to understand How the Redolog Buffer Cache Works and How to detect and resolve tuning problems related with this SGA structure.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;Contents:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#one&quot;&gt;1. What is the Redolog Buffer&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#two&quot;&gt;2. Redolog Latches&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#copylatch&quot;&gt;Redo Copy latch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#alloclatch&quot;&gt;Redo  allocation latch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#writelacth&quot;&gt;Redo writing latch&lt;/a&gt;&lt;/li&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#three&quot;&gt;3. Instance Parameters Related with the Redolog Latches&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#four&quot;&gt;4. Tuning Redolog Buffer Performance&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#Latch&quot;&gt;Latch contention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#space&quot;&gt;Request for space contention&lt;/a&gt;&lt;/li&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;TUNING THE REDOLOG BUFFER&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;one&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;1. What is the Redolog Buffer&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The redo log buffer is a circular buffer in the SGA that holds information about changes made to the database. This information is stored in redo entries. Redo entries contain the information necessary to reconstruct, or redo, changes made to the database . Redo entries are used for database recovery, if necessary.Redo entries are copied by Oracle server processes from the user&amp;#8217;s memory space to the redo log buffer in the SGA. The redo entries take up continuous, sequential space in the buffer. The background process LGWR writes the redo log buffer to the active online redo log file (or group of files) on disk.&lt;/p&gt;
&lt;p&gt;The initialization parameter LOG_BUFFER determines the size (in bytes) of the redo log buffer. In general, larger values reduce log file I/O, particularly if transactions are long or numerous. The default setting is four times the maximum data block size for the host operating system.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;two&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2. Redolog Latches&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
When a change to a data block needs to be done, it requires to create a redo record in the redolog buffer executing the following steps:&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt; Ensure that no other processes has generated a higher SCN&lt;/li&gt;
&lt;li&gt; Find for space available to write the redo record. If there are not space available a the LGWR must write to disk or issue a log switch&lt;/li&gt;
&lt;li&gt; Allocate the space needed in the redo log buffer&lt;/li&gt;
&lt;li&gt; Copy the redo record to the log buffer and link it to the appropriate structures for recovery purposes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The database has three redo latches to handle this process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a name=&quot;copylatch&quot;&gt;&lt;/a&gt;Redo Copy latch
&lt;ul&gt;The &lt;em&gt;redo copy latch&lt;/em&gt; is acquired for the whole duration of the process described above. The init.ora LOG_SIMULTANEOUS_COPIES determines the  number of redo copy latches. It is only released when a log switch is generated to release free space and re-acquired once the log switch ends.&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a name=&quot;alloclatch&quot;&gt;&lt;/a&gt;Redo  allocation latch
&lt;ul&gt;The redo allocation latch is acquired to allocate memory space in the  log buffer. Before Oracle9.2, the redo allocation latch is unique and thus serializes the writing of entries to the log buffer cache of the SGA. In Oracle 9.2. Entreprise Edition, the number of redo allocation latches  is determined by init.ora LOG_PARALLELISM.   The redo allocation latch  allocates space in the log buffer cache for each transaction entry.   If transactions are small, or if there is only one CPU on the server, then  the redo allocation latch also copies the transaction data into the log buffer  cache. If a logswitch is needed to get free space this latch is released as  well with the&lt;em&gt; redo copy latch.&lt;/em&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a name=&quot;writelatch&quot;&gt;&lt;/a&gt;Redo writing latch
&lt;ul&gt;This unique latch prevent multiple processes posting the LGWR  process requesting log switch simultaneously. A process that needs free space must acquire the latch before of deciding whether to post the LGWR to perform a write, execute a log switch or just wait.&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;three&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;3. Instance Parameters Related with the Redolog Latches&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;In Oracle7 and Oracle8.0, there are two parameters that modify the  behavior of the latch allocation in the redolog buffer: LOG_SIMULTANEOUS_COPIES  (This parameter controls the number of &lt;em&gt;redo copy latches&lt;/em&gt; when the  system has more than one CPU),  and LOG_SMALL_ENTRY_MAX_SIZE. When  LOG_SIMULTANEOUS_COPIES is set to a non-zero value, and the size of the  transaction entry is smaller than the value of the LOG_SMALL_ENTRY_MAX_SIZE  parameter then the copy of the transaction entry into the log buffer cache  is performed by the &lt;em&gt;redo allocation latch&lt;/em&gt;.  If the size of the  transaction entry exceeds LOG_SMALL_ENTRY_MAX_SIZE, then the transaction entry  is copied into the log buffer cache by the &lt;em&gt;redo copy latch&lt;/em&gt;.In Oracle8i and Oracle9.0, a redo copy latch is always required regardless  of the redo size so the check is no longer performed. The init.ora  LOG_SIMULTANEOUS_COPIES becomes obsolete and the number of  redo copy latches defaults to twice the number of cpus. The parameter  LOG_SMALL_ENTRY_MAX_SIZE is also obsolete. For further detail on the change  of this parameters in Oracle 8i see&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;id=94271.1&amp;amp;type=NOT&quot;&gt;Note:94271.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In Oracle9.2, multiple redo allocation latches become possible with init.ora LOG_PARALLELISM. The log buffer is split in multiple LOG_PARALLELISM areas  that each have a size of init.ora LOG_BUFFER. The allocation job of each area is protected by a specific redo allocation latch. The number of redo copy latches is still determined by the number of cpus&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;four&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Detecting and Resolving Redolog Buffer Performance Problem&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
Contention in the redolog buffer will impact the performance of the database since all DML and DDL must record a entry before of being executed. Contention can be seen as a latch contention or as excessive request for free space in the log buffer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note: In general log buffer contention is not frequent problem unless the  latches already mentioned are consistently in the top wait events. Experience usually shows redo IO throughput is the main culprit of redo contention. &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The database allow you to detect both types of contention as described below:&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a name=&quot;Latch&quot;&gt;&lt;/a&gt;Latch contention&lt;/li&gt;
&lt;p&gt;The following query determines the miss ratio and the &amp;#8220;immediate&amp;#8221; miss ratio for redolog latches.&lt;/p&gt;
&lt;p&gt;SELECT  substr(ln.name, 1, 20), gets, misses, immediate_gets, immediate_misses&lt;br /&gt;
FROM v$latch l, v$latchname ln&lt;br /&gt;
WHERE   ln.name in (&amp;#8216;redo allocation&amp;#8217;, &amp;#8216;redo copy&amp;#8217;)&lt;br /&gt;
and ln.latch# = l.latch#;&lt;/p&gt;
&lt;p&gt;If the ratio of MISSES to GETS exceeds 1%, or the ratio of IMMEDIATE_MISSES to (IMMEDIATE_GETS + IMMEDIATE_MISSES) exceeds 1%, there is latch contention.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note: Oracle recommends to tune first the &lt;em&gt;redo allocation latch&lt;/em&gt; rather than the &lt;em&gt;redo copy latch.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Oracle7 and Oracle8.0:&lt;br /&gt;
If the contention is caused by &lt;em&gt;redo allocation latch&lt;/em&gt; decrease the value of LOG_SMALL_ENTRY_MAX_SIZE. The recommended value is the average of redo size which can be calculated as (redo size/redo entries) from V$SYSSTAT.&lt;br /&gt;
If you find &lt;em&gt;redo copy latch &lt;/em&gt;contention, you can increase the parameter LOG_SIMULTANEOUS_COPIES to have more latches available. The recommended value is twice the numbers of CPUs.&lt;/p&gt;
&lt;p&gt;In Oracle8i and Oracle9.0:&lt;br /&gt;
If the contention is caused by &lt;em&gt;redo allocation latch&lt;/em&gt; you can either use the NOLOGGING option to reduce the amount of redo log entries for certain operations (See &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;id=147474.1&amp;amp;type=NOT&quot;&gt;Note:147474.1&lt;/a&gt;) or reduce the load on the latch increasing the LOG_BUFFER PARAMETER.&lt;br /&gt;
@You can reduce the load on the latch as well using the parameter _LOG_IO_SIZE&lt;br /&gt;
@described in the @&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;id=31283.1&amp;amp;type=NOT&quot;&gt;Note:31283.1&lt;/a&gt;&lt;br /&gt;
If you find &lt;em&gt;redo copy latch &lt;/em&gt;contention, you can increase the hidden init.ora _LOG_SIMULTANEOUS_COPIES to have more latches available. The default is twice the numbers of CPUs.&lt;/p&gt;
&lt;p&gt;In Oracle 9.2:&lt;br /&gt;
If the contention is caused by &lt;em&gt;redo allocation latch&lt;/em&gt; you can try to increase their number via init.ora LOG_PARALLELISM&lt;br /&gt;
If you find &lt;em&gt;redo copy latch &lt;/em&gt;contention, you can increase the hidden init.ora _LOG_SIMULTANEOUS_COPIES to have more latches  available. The default is twice the numbers of CPUs.&lt;/p&gt;
&lt;p&gt;In Oracle 10.2:&lt;br /&gt;
The statistic REDO BUFFER ALLOCATION RETRIES reflects the number of times a&lt;br /&gt;
user process waits for space in the redo log buffer. The value of redo buffer&lt;br /&gt;
allocation retries should be near zero over an interval. If this value increments&lt;br /&gt;
consistently, then processes have had to wait for space in the redo log buffer.&lt;br /&gt;
The wait can be caused by the log buffer being too small or by checkpointing.&lt;br /&gt;
Increase the size of the redo log buffer, if necessary, by changing the value of&lt;br /&gt;
the initialization parameter LOG_BUFFER. The value of this parameter is expressed&lt;br /&gt;
in bytes.&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a name=&quot;space&quot;&gt;&lt;/a&gt;Request for space contention&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
The statistic &amp;#8220;redo log space requests&amp;#8221; reflects the number of times a user process waits for space in the redo log file, not the buffer space ..  This statistic is available through the dynamic performance table  V$SYSSTAT. By default, this table is only available to the user SYS and to  users granted SELECT ANY TABLE system privilege, such as SYSTEM.   Monitor this statistic over a period of time while&lt;br /&gt;
your application is running with this query:SELECT name, value&lt;br /&gt;
FROM v$sysstat&lt;br /&gt;
WHERE name = &amp;#8216;redo log space requests&amp;#8217;;&lt;/p&gt;
&lt;p&gt;The value of &amp;#8220;redo log space requests&amp;#8221; should be near 0. If this value  increments consistently, processes have had to wait for space in the buffer. This may be caused the checkpointing or log switching.   Improve thus the checkpointing or archiving process.&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&lt;img id=&quot;collapseImg2&quot; onclick=&quot;toggleVisibility(this.id, 'collapsibleRelatedData');&quot; src=&quot;https://support.oracle.com/CSP/images/collapse_white.png&quot; alt=&quot;Show Related Information&quot; /&gt; &lt;strong&gt;Related&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&quot;collapsibleRelatedData&quot;&gt;
&lt;hr size=&quot;1&quot; /&gt;&lt;strong&gt;Products&lt;/strong&gt;&lt;br /&gt;
&lt;hr size=&quot;1&quot; /&gt;
&lt;ul&gt;
&lt;li&gt; Oracle Database Products &amp;gt; Oracle Database &amp;gt; Oracle Database &amp;gt; Oracle Server &amp;#8211; Enterprise Edition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Keywords&lt;/strong&gt;&lt;br /&gt;
&lt;hr size=&quot;1&quot; /&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;2&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;LOG_BUFFER; LOG_SIMULTANEOUS_COPIES; LOG_SMALL_ENTRY_MAX_SIZE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;!--{{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF}}--&gt;&lt;/p&gt;</content><thr:total>0</thr:total><description>&lt;strong&gt;Tuning the Redolog Buffer Cache and Resolving Redo Latch Contention [ID 147471.1]&lt;/strong&gt;








&lt;em&gt;Modified&lt;/em&gt; 16-JUL-2009     &lt;em&gt;Type&lt;/em&gt; BULLETIN     &lt;em&gt;Status&lt;/em&gt; PUBLISHED
[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/01/tuning-the-redo-log-buffer-cache-and-resolving-redo-latch-contention'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794220/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/tuning-the-redo-log-buffer-cache-and-resolving-redo-latch-contention&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794220/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794220/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;table border=&quot;0&quot; cellspacing=&quot;6&quot; cellpadding=&quot;0&quot; width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan=&quot;4&quot; align=&quot;left&quot; valign=&quot;top&quot;&gt;&lt;strong&gt;Tuning the Redolog Buffer Cache and Resolving Redo Latch Contention [ID 147471.1]&lt;/strong&gt;&lt;/td&gt;
&lt;td colspan=&quot;2&quot; valign=&quot;top&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;6&quot; align=&quot;left&quot; valign=&quot;top&quot;&gt;
&lt;hr size=&quot;1&quot; /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot; width=&quot;25%&quot; valign=&quot;top&quot;&gt;&lt;/td&gt;
&lt;td colspan=&quot;3&quot; width=&quot;50%&quot; valign=&quot;top&quot;&gt;&lt;em&gt;Modified&lt;/em&gt; 16-JUL-2009     &lt;em&gt;Type&lt;/em&gt; BULLETIN     &lt;em&gt;Status&lt;/em&gt; PUBLISHED&lt;/td&gt;
&lt;td valign=&quot;top&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;Purpose:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;This article provide detailed information to understand How the Redolog Buffer Cache Works and How to detect and resolve tuning problems related with this SGA structure.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;Contents:&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#one&quot;&gt;1. What is the Redolog Buffer&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#two&quot;&gt;2. Redolog Latches&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#copylatch&quot;&gt;Redo Copy latch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#alloclatch&quot;&gt;Redo  allocation latch&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#writelacth&quot;&gt;Redo writing latch&lt;/a&gt;&lt;/li&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#three&quot;&gt;3. Instance Parameters Related with the Redolog Latches&lt;/a&gt;&lt;br /&gt;
&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#four&quot;&gt;4. Tuning Redolog Buffer Performance&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#Latch&quot;&gt;Latch contention&lt;/a&gt;&lt;/li&gt;
&lt;li&gt; &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;type=NOT&amp;amp;id=147471.1#space&quot;&gt;Request for space contention&lt;/a&gt;&lt;/li&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;font-size: xx-small;&quot;&gt;TUNING THE REDOLOG BUFFER&lt;/span&gt;&lt;/span&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;one&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;1. What is the Redolog Buffer&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The redo log buffer is a circular buffer in the SGA that holds information about changes made to the database. This information is stored in redo entries. Redo entries contain the information necessary to reconstruct, or redo, changes made to the database . Redo entries are used for database recovery, if necessary.Redo entries are copied by Oracle server processes from the user&amp;#8217;s memory space to the redo log buffer in the SGA. The redo entries take up continuous, sequential space in the buffer. The background process LGWR writes the redo log buffer to the active online redo log file (or group of files) on disk.&lt;/p&gt;
&lt;p&gt;The initialization parameter LOG_BUFFER determines the size (in bytes) of the redo log buffer. In general, larger values reduce log file I/O, particularly if transactions are long or numerous. The default setting is four times the maximum data block size for the host operating system.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;two&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;2. Redolog Latches&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
When a change to a data block needs to be done, it requires to create a redo record in the redolog buffer executing the following steps:&lt;/p&gt;&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt; Ensure that no other processes has generated a higher SCN&lt;/li&gt;
&lt;li&gt; Find for space available to write the redo record. If there are not space available a the LGWR must write to disk or issue a log switch&lt;/li&gt;
&lt;li&gt; Allocate the space needed in the redo log buffer&lt;/li&gt;
&lt;li&gt; Copy the redo record to the log buffer and link it to the appropriate structures for recovery purposes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The database has three redo latches to handle this process:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a name=&quot;copylatch&quot;&gt;&lt;/a&gt;Redo Copy latch
&lt;ul&gt;The &lt;em&gt;redo copy latch&lt;/em&gt; is acquired for the whole duration of the process described above. The init.ora LOG_SIMULTANEOUS_COPIES determines the  number of redo copy latches. It is only released when a log switch is generated to release free space and re-acquired once the log switch ends.&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a name=&quot;alloclatch&quot;&gt;&lt;/a&gt;Redo  allocation latch
&lt;ul&gt;The redo allocation latch is acquired to allocate memory space in the  log buffer. Before Oracle9.2, the redo allocation latch is unique and thus serializes the writing of entries to the log buffer cache of the SGA. In Oracle 9.2. Entreprise Edition, the number of redo allocation latches  is determined by init.ora LOG_PARALLELISM.   The redo allocation latch  allocates space in the log buffer cache for each transaction entry.   If transactions are small, or if there is only one CPU on the server, then  the redo allocation latch also copies the transaction data into the log buffer  cache. If a logswitch is needed to get free space this latch is released as  well with the&lt;em&gt; redo copy latch.&lt;/em&gt;&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; &lt;a name=&quot;writelatch&quot;&gt;&lt;/a&gt;Redo writing latch
&lt;ul&gt;This unique latch prevent multiple processes posting the LGWR  process requesting log switch simultaneously. A process that needs free space must acquire the latch before of deciding whether to post the LGWR to perform a write, execute a log switch or just wait.&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;three&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;3. Instance Parameters Related with the Redolog Latches&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;In Oracle7 and Oracle8.0, there are two parameters that modify the  behavior of the latch allocation in the redolog buffer: LOG_SIMULTANEOUS_COPIES  (This parameter controls the number of &lt;em&gt;redo copy latches&lt;/em&gt; when the  system has more than one CPU),  and LOG_SMALL_ENTRY_MAX_SIZE. When  LOG_SIMULTANEOUS_COPIES is set to a non-zero value, and the size of the  transaction entry is smaller than the value of the LOG_SMALL_ENTRY_MAX_SIZE  parameter then the copy of the transaction entry into the log buffer cache  is performed by the &lt;em&gt;redo allocation latch&lt;/em&gt;.  If the size of the  transaction entry exceeds LOG_SMALL_ENTRY_MAX_SIZE, then the transaction entry  is copied into the log buffer cache by the &lt;em&gt;redo copy latch&lt;/em&gt;.In Oracle8i and Oracle9.0, a redo copy latch is always required regardless  of the redo size so the check is no longer performed. The init.ora  LOG_SIMULTANEOUS_COPIES becomes obsolete and the number of  redo copy latches defaults to twice the number of cpus. The parameter  LOG_SMALL_ENTRY_MAX_SIZE is also obsolete. For further detail on the change  of this parameters in Oracle 8i see&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;id=94271.1&amp;amp;type=NOT&quot;&gt;Note:94271.1&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In Oracle9.2, multiple redo allocation latches become possible with init.ora LOG_PARALLELISM. The log buffer is split in multiple LOG_PARALLELISM areas  that each have a size of init.ora LOG_BUFFER. The allocation job of each area is protected by a specific redo allocation latch. The number of redo copy latches is still determined by the number of cpus&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;a name=&quot;four&quot;&gt;&lt;/a&gt;&lt;span style=&quot;text-decoration: underline;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4. Detecting and Resolving Redolog Buffer Performance Problem&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
Contention in the redolog buffer will impact the performance of the database since all DML and DDL must record a entry before of being executed. Contention can be seen as a latch contention or as excessive request for free space in the log buffer.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note: In general log buffer contention is not frequent problem unless the  latches already mentioned are consistently in the top wait events. Experience usually shows redo IO throughput is the main culprit of redo contention. &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The database allow you to detect both types of contention as described below:&lt;/p&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a name=&quot;Latch&quot;&gt;&lt;/a&gt;Latch contention&lt;/li&gt;
&lt;p&gt;The following query determines the miss ratio and the &amp;#8220;immediate&amp;#8221; miss ratio for redolog latches.&lt;/p&gt;
&lt;p&gt;SELECT  substr(ln.name, 1, 20), gets, misses, immediate_gets, immediate_misses&lt;br /&gt;
FROM v$latch l, v$latchname ln&lt;br /&gt;
WHERE   ln.name in (&amp;#8216;redo allocation&amp;#8217;, &amp;#8216;redo copy&amp;#8217;)&lt;br /&gt;
and ln.latch# = l.latch#;&lt;/p&gt;
&lt;p&gt;If the ratio of MISSES to GETS exceeds 1%, or the ratio of IMMEDIATE_MISSES to (IMMEDIATE_GETS + IMMEDIATE_MISSES) exceeds 1%, there is latch contention.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note: Oracle recommends to tune first the &lt;em&gt;redo allocation latch&lt;/em&gt; rather than the &lt;em&gt;redo copy latch.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;In Oracle7 and Oracle8.0:&lt;br /&gt;
If the contention is caused by &lt;em&gt;redo allocation latch&lt;/em&gt; decrease the value of LOG_SMALL_ENTRY_MAX_SIZE. The recommended value is the average of redo size which can be calculated as (redo size/redo entries) from V$SYSSTAT.&lt;br /&gt;
If you find &lt;em&gt;redo copy latch &lt;/em&gt;contention, you can increase the parameter LOG_SIMULTANEOUS_COPIES to have more latches available. The recommended value is twice the numbers of CPUs.&lt;/p&gt;
&lt;p&gt;In Oracle8i and Oracle9.0:&lt;br /&gt;
If the contention is caused by &lt;em&gt;redo allocation latch&lt;/em&gt; you can either use the NOLOGGING option to reduce the amount of redo log entries for certain operations (See &lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;id=147474.1&amp;amp;type=NOT&quot;&gt;Note:147474.1&lt;/a&gt;) or reduce the load on the latch increasing the LOG_BUFFER PARAMETER.&lt;br /&gt;
@You can reduce the load on the latch as well using the parameter _LOG_IO_SIZE&lt;br /&gt;
@described in the @&lt;a href=&quot;https://support.oracle.com/CSP/main/article?cmd=show&amp;amp;id=31283.1&amp;amp;type=NOT&quot;&gt;Note:31283.1&lt;/a&gt;&lt;br /&gt;
If you find &lt;em&gt;redo copy latch &lt;/em&gt;contention, you can increase the hidden init.ora _LOG_SIMULTANEOUS_COPIES to have more latches available. The default is twice the numbers of CPUs.&lt;/p&gt;
&lt;p&gt;In Oracle 9.2:&lt;br /&gt;
If the contention is caused by &lt;em&gt;redo allocation latch&lt;/em&gt; you can try to increase their number via init.ora LOG_PARALLELISM&lt;br /&gt;
If you find &lt;em&gt;redo copy latch &lt;/em&gt;contention, you can increase the hidden init.ora _LOG_SIMULTANEOUS_COPIES to have more latches  available. The default is twice the numbers of CPUs.&lt;/p&gt;
&lt;p&gt;In Oracle 10.2:&lt;br /&gt;
The statistic REDO BUFFER ALLOCATION RETRIES reflects the number of times a&lt;br /&gt;
user process waits for space in the redo log buffer. The value of redo buffer&lt;br /&gt;
allocation retries should be near zero over an interval. If this value increments&lt;br /&gt;
consistently, then processes have had to wait for space in the redo log buffer.&lt;br /&gt;
The wait can be caused by the log buffer being too small or by checkpointing.&lt;br /&gt;
Increase the size of the redo log buffer, if necessary, by changing the value of&lt;br /&gt;
the initialization parameter LOG_BUFFER. The value of this parameter is expressed&lt;br /&gt;
in bytes.&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;ul&gt;
&lt;li&gt; &lt;a name=&quot;space&quot;&gt;&lt;/a&gt;Request for space contention&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
The statistic &amp;#8220;redo log space requests&amp;#8221; reflects the number of times a user process waits for space in the redo log file, not the buffer space ..  This statistic is available through the dynamic performance table  V$SYSSTAT. By default, this table is only available to the user SYS and to  users granted SELECT ANY TABLE system privilege, such as SYSTEM.   Monitor this statistic over a period of time while&lt;br /&gt;
your application is running with this query:SELECT name, value&lt;br /&gt;
FROM v$sysstat&lt;br /&gt;
WHERE name = &amp;#8216;redo log space requests&amp;#8217;;&lt;/p&gt;
&lt;p&gt;The value of &amp;#8220;redo log space requests&amp;#8221; should be near 0. If this value  increments consistently, processes have had to wait for space in the buffer. This may be caused the checkpointing or log switching.   Improve thus the checkpointing or archiving process.&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;table width=&quot;100%&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td colspan=&quot;2&quot;&gt;&lt;img id=&quot;collapseImg2&quot; onclick=&quot;toggleVisibility(this.id, 'collapsibleRelatedData');&quot; src=&quot;https://support.oracle.com/CSP/images/collapse_white.png&quot; alt=&quot;Show Related Information&quot; /&gt; &lt;strong&gt;Related&lt;/strong&gt;&lt;/p&gt;
&lt;div id=&quot;collapsibleRelatedData&quot;&gt;
&lt;hr size=&quot;1&quot; /&gt;&lt;strong&gt;Products&lt;/strong&gt;&lt;br /&gt;
&lt;hr size=&quot;1&quot; /&gt;
&lt;ul&gt;
&lt;li&gt; Oracle Database Products &amp;gt; Oracle Database &amp;gt; Oracle Database &amp;gt; Oracle Server &amp;#8211; Enterprise Edition&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Keywords&lt;/strong&gt;&lt;br /&gt;
&lt;hr size=&quot;1&quot; /&gt;
&lt;table border=&quot;0&quot; cellspacing=&quot;2&quot; cellpadding=&quot;0&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td valign=&quot;top&quot;&gt;LOG_BUFFER; LOG_SIMULTANEOUS_COPIES; LOG_SMALL_ENTRY_MAX_SIZE&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;!--{{FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF}}--&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794220/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/tuning-the-redo-log-buffer-cache-and-resolving-redo-latch-contention&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794220/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794220/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">Oracle</category><category domain="http://www.dbadoc.com">buffer</category><category domain="http://www.dbadoc.com">log</category><category domain="http://www.dbadoc.com">redo</category><pubDate>Fri, 22 Jan 2010 16:54:10 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2042</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/01/tuning-the-redo-log-buffer-cache-and-resolving-redo-latch-contention</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794220/5445352</fs:itemid></item><item><title>ora92中跟staspacck相关的两个脚本</title><link atom:type="text/html">http://www.dbadoc.com/2010/01/ora92_statspack</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2040</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/01/ora92_statspack">&lt;p&gt;1.spuexp.par&lt;/p&gt;
&lt;p&gt;是个用于exp的参数文件，用于导出statspack表的数据，其内容为：&lt;/p&gt;
&lt;p&gt;$ cat spuexp.par&lt;/p&gt;
&lt;p&gt;file=spuexp.dmp log=spuexp.log compress=y grants=y indexes=y rows=y constraints=y owner=PERFSTAT consistent=y&lt;/p&gt;
&lt;p&gt;使用方法为:  exp perfstat/perfstat parfile=spuexp.par&lt;/p&gt;
&lt;p&gt;2.   sprepsql.sql  用于根据给定的前后两个snap id 和SQL Hash值生成SQL的报告，例子如下：&lt;/p&gt;
&lt;p&gt;STATSPACK SQL report for Hash Value: 2618850598&lt;/p&gt;
&lt;p&gt;DB Name         DB Id    Instance     Inst Num Release     Cluster Host&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8211; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211; &amp;#8212;&amp;#8212;- &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
WHCJ          3835953590 whcj                1 9.2.0.7.0   NO      localhost&lt;/p&gt;
&lt;p&gt;Start Id     Start Time         End Id      End Time       Duration(mins)&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;- &amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;- &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
1 25-Oct-10 09:49:23          2 25-Oct-10 10:11:44           22.35&lt;/p&gt;
&lt;p&gt;SQL Statistics&lt;br /&gt;
~~~~~~~~~~~~~~&lt;br /&gt;
-&amp;gt; CPU and Elapsed Time are in seconds (s) for Statement Total and in&lt;br /&gt;
milliseconds (ms) for Per Execute&lt;br /&gt;
% Snap&lt;br /&gt;
Statement Total      Per Execute   Total&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;  &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;  &amp;#8212;&amp;#8212;&lt;br /&gt;
Buffer Gets:               3              3.0     .01&lt;br /&gt;
Disk Reads:               0              0.0     .00&lt;br /&gt;
Rows processed:               0              0.0&lt;br /&gt;
CPU Time(s/ms):               0               .0&lt;br /&gt;
Elapsed Time(s/ms):               0               .1&lt;br /&gt;
Sorts:               0               .0&lt;br /&gt;
Parse Calls:               1              1.0&lt;br /&gt;
Invalidations:               0&lt;br /&gt;
Version count:               1&lt;br /&gt;
Sharable Mem(K):              17&lt;br /&gt;
Executions:               1&lt;/p&gt;
&lt;p&gt;SQL Text&lt;br /&gt;
~~~~~~~~&lt;br /&gt;
select local_tran_id, global_tran_fmt, global_oracle_id, global_&lt;br /&gt;
foreign_id,        state, status, heuristic_dflt,        session&lt;br /&gt;
_vector, reco_vector, 3600*24*(sysdate-reco_time),        3600*2&lt;br /&gt;
4*(sysdate-nvl(heuristic_time,fail_time)), global_commit#, type#&lt;br /&gt;
from pending_trans$  where session_vector != &amp;#8216;00000000&amp;#8242;&lt;/p&gt;
&lt;p&gt;Plans in shared pool between Begin and End Snap Ids&lt;br /&gt;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;
Shows the Execution Plans found in the shared pool between the begin and end&lt;br /&gt;
snapshots specified.  The values for Rows, Bytes and Cost shown below are those&lt;br /&gt;
which existed at the time the first-ever snapshot captured this plan &amp;#8211; these&lt;br /&gt;
values often change over time, and so may not be indicative of current values&lt;br /&gt;
-&amp;gt; Rows indicates Cardinality, PHV is Plan Hash Value&lt;br /&gt;
-&amp;gt; ordered by Plan Hash Value&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
| Operation                      | PHV/Object Name     |  Rows | Bytes|   Cost |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;/p&gt;
&lt;p&gt;End of Report&lt;/p&gt;</content><thr:total>0</thr:total><description>1.spuexp.par
是个用于exp的参数文件，用于导出statspack表的数据，其内容为：
$ cat spuexp.par
file=spuexp.dmp log=spuexp.log compress=y grants=y indexes=y rows=y constraints=y o[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/01/ora92_statspack'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794221/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/ora92_statspack&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794221/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794221/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;1.spuexp.par&lt;/p&gt;
&lt;p&gt;是个用于exp的参数文件，用于导出statspack表的数据，其内容为：&lt;/p&gt;
&lt;p&gt;$ cat spuexp.par&lt;/p&gt;
&lt;p&gt;file=spuexp.dmp log=spuexp.log compress=y grants=y indexes=y rows=y constraints=y owner=PERFSTAT consistent=y&lt;/p&gt;
&lt;p&gt;使用方法为:  exp perfstat/perfstat parfile=spuexp.par&lt;/p&gt;
&lt;p&gt;2.   sprepsql.sql  用于根据给定的前后两个snap id 和SQL Hash值生成SQL的报告，例子如下：&lt;/p&gt;
&lt;p&gt;STATSPACK SQL report for Hash Value: 2618850598&lt;/p&gt;
&lt;p&gt;DB Name         DB Id    Instance     Inst Num Release     Cluster Host&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8211; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211; &amp;#8212;&amp;#8212;- &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&lt;br /&gt;
WHCJ          3835953590 whcj                1 9.2.0.7.0   NO      localhost&lt;/p&gt;
&lt;p&gt;Start Id     Start Time         End Id      End Time       Duration(mins)&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;- &amp;#8212;&amp;#8212;&amp;#8212; &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;- &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
1 25-Oct-10 09:49:23          2 25-Oct-10 10:11:44           22.35&lt;/p&gt;
&lt;p&gt;SQL Statistics&lt;br /&gt;
~~~~~~~~~~~~~~&lt;br /&gt;
-&amp;gt; CPU and Elapsed Time are in seconds (s) for Statement Total and in&lt;br /&gt;
milliseconds (ms) for Per Execute&lt;br /&gt;
% Snap&lt;br /&gt;
Statement Total      Per Execute   Total&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;  &amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;  &amp;#8212;&amp;#8212;&lt;br /&gt;
Buffer Gets:               3              3.0     .01&lt;br /&gt;
Disk Reads:               0              0.0     .00&lt;br /&gt;
Rows processed:               0              0.0&lt;br /&gt;
CPU Time(s/ms):               0               .0&lt;br /&gt;
Elapsed Time(s/ms):               0               .1&lt;br /&gt;
Sorts:               0               .0&lt;br /&gt;
Parse Calls:               1              1.0&lt;br /&gt;
Invalidations:               0&lt;br /&gt;
Version count:               1&lt;br /&gt;
Sharable Mem(K):              17&lt;br /&gt;
Executions:               1&lt;/p&gt;
&lt;p&gt;SQL Text&lt;br /&gt;
~~~~~~~~&lt;br /&gt;
select local_tran_id, global_tran_fmt, global_oracle_id, global_&lt;br /&gt;
foreign_id,        state, status, heuristic_dflt,        session&lt;br /&gt;
_vector, reco_vector, 3600*24*(sysdate-reco_time),        3600*2&lt;br /&gt;
4*(sysdate-nvl(heuristic_time,fail_time)), global_commit#, type#&lt;br /&gt;
from pending_trans$  where session_vector != &amp;#8216;00000000&amp;#8242;&lt;/p&gt;
&lt;p&gt;Plans in shared pool between Begin and End Snap Ids&lt;br /&gt;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~&lt;br /&gt;
Shows the Execution Plans found in the shared pool between the begin and end&lt;br /&gt;
snapshots specified.  The values for Rows, Bytes and Cost shown below are those&lt;br /&gt;
which existed at the time the first-ever snapshot captured this plan &amp;#8211; these&lt;br /&gt;
values often change over time, and so may not be indicative of current values&lt;br /&gt;
-&amp;gt; Rows indicates Cardinality, PHV is Plan Hash Value&lt;br /&gt;
-&amp;gt; ordered by Plan Hash Value&lt;/p&gt;
&lt;p&gt;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
| Operation                      | PHV/Object Name     |  Rows | Bytes|   Cost |&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;br /&gt;
&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8212;&amp;#8211;&lt;/p&gt;
&lt;p&gt;End of Report&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794221/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/ora92_statspack&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794221/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794221/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">Oracle</category><category domain="http://www.dbadoc.com">sprepsql.sql</category><category domain="http://www.dbadoc.com">spuexp.par</category><category domain="http://www.dbadoc.com">statspack</category><pubDate>Fri, 15 Jan 2010 10:08:58 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2040</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/01/ora92_statspack</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794221/5445352</fs:itemid></item><item><title>2010</title><link atom:type="text/html">http://www.dbadoc.com/2010/01/2010</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2037</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/01/2010">&lt;p&gt;09年是轮回的一年，这一年是我的本命年，发生了很多很多的事，工作的，生活的，开心的，不开心的，一件件在脑中晃过，无论开心与否，无论痛苦与否，都已飘然远去，消散在自己背后的影子里。宠辱不惊，看庭前花开花落；去留无意，望天空云卷云舒。这是何等的一种心境，而我要做的就是努力看齐。&amp;#8212;&amp;#8211;这句是写给2010年自己的话。&lt;/p&gt;
&lt;p&gt;两个轮回了，一切又回到了原点。掐指算来，人生能干点什么，或者有意义的时间也大约就那么3个轮回，对于我来说，就是从2010开始的后三个轮回，区区36年而已，抛去吃喝拉撒玩乐，能认真干些什么事的时间算一个轮回吧，12年。&lt;/p&gt;
&lt;p&gt;加油吧，或迷茫，或疯狂，或瞎忙的孩子们！&lt;/p&gt;
&lt;p&gt;07年底的时候写过一篇&lt;a href=&quot;http://www.dbadoc.com/2007/12/1227&quot; target=&quot;_blank&quot;&gt;年终总结&lt;/a&gt;，08年底的时候也写过一篇&lt;a href=&quot;http://www.dbadoc.com/2009/01/1018&quot; target=&quot;_blank&quot;&gt;年终总结&lt;/a&gt;。当初计划的09年要做的几件事：&lt;/p&gt;
&lt;p&gt;1。申请一个个人技术站点。&lt;/p&gt;
&lt;p&gt;2。读2本Oracle图书，看两篇Oracle文挡，研究两个Oracle专题。&lt;/p&gt;
&lt;p&gt;3。去一个没有去过的地方。&lt;/p&gt;
&lt;p&gt;4。锻炼身体。&lt;/p&gt;
&lt;p&gt;5。学好英文。&lt;/p&gt;
&lt;p&gt;6。买一个镜头，拍一些自己满意的照片。&lt;/p&gt;
&lt;p&gt;比较欣慰的是，现在看来，这些计划也大都完成了：&lt;/p&gt;
&lt;p&gt;1。09年年初的时候，建立了这个技术站点，钱倒是没花多少，不过话费了很多的时间，一点一点亲手把他建立起来的，从申请域名，到找空间，到安装wordpress，再到第一篇文章，虽然他并没有比那些第三方的博客好用多少，但是，不亲自去弄，就不知道这其中的辛苦与快乐！这种快乐是不亲自去尝试的人永远也不会体会到的。&lt;/p&gt;
&lt;p&gt;值得一提的是：&lt;span style=&quot;color: #000000;&quot;&gt;还为了一个人，一点一点的建立了另外一个&lt;/span&gt;&lt;strong&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;a href=&quot;http://www.wobusu.com/&quot; target=&quot;_blank&quot;&gt;站点&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;，付出了全部的真情和心血，家里没有网，去网吧一点一点的弄起来，什么都追求尽量做到最好，比我自己的站点付出了更多更多的精力。付出了很多，并不见得有人真正在乎你的付出，你含辛茹苦的付出，也许只被别人不屑的弃之一旁，剩下的也徒有伤悲之人。往事如梭，不提也罢，不过这个站点，我想我会一直保留下去，那也是一段真情和一段真心的见证吧。&lt;/p&gt;
&lt;p&gt;2。总体来说做的不是很好，书断断续续的看了两个半本，加起来估计都不到一本，回首看看，自己这一年在专业技术上的进步实在有限，也许是本命年人变的很浮躁，也许是放了很多的精力在别的事情上面，言而总之，总而言之，这浮躁的本命年已经过去，10年，我会好好努力加油的，多研究自己本职技术，其他的都是虚的，只有这些才是自己的，谁也抢不走。&lt;/p&gt;
&lt;p&gt;3。去一个没有去过的地方，应该是没有完成，本意是想去一个没有去过的地方旅游，比如西双版纳，比如海南，又比如世界上某个神奇的角落，可是小的地方也去了几个，比如去了天津，去了长城，新的一年，我应该多走走，多看看，人这一辈子不长，能去的地方也实在有限，何不乘着年轻，多走走呢？&lt;/p&gt;
&lt;p&gt;4。比较欣慰又比较无奈自己的就是这锻炼身体了，年初时，雄心勃勃，办了全年的游泳卡，自己想的，一定可以坚持游一年，刚开始，却也坚持了，感觉身体也确实好了些，自己能感觉得到，后来，各种原因，各种借口让自己的游泳计划在坚持了5个月之后没有坚持下去。现在，天异常的冷，专家说是又一个冰河世纪到来了，想想去游泳就很冷，自己对自己唯一的一个期许就是年前能再去游泳馆一次，哪怕看看也行。&lt;/p&gt;
&lt;p&gt;5，6，英文还是没有多少进步，看了一些英文电影，不看字幕虽然也大概能听懂，但感觉反应却总是滞后剧情的发展，看了些走遍美国，还一直发给某人看，说学好英文，可惜的是我们都没有坚持学下去吧。至于摄影拍照片，唯一想说的是当兴趣遇到烧钱，我也许只能举着我的小痰盂一直拍下去了。镜头也许暂时不会买了，因为本命年，我烧了很多的钱在其他方面，很傻很傻。&lt;/p&gt;
&lt;p&gt;无论乐意与否，无论坦然与否，09年，本命年都已经成为历史，永久的历史。人要向前看，在10年还不太晚的开头上，依然给自己定几个不太遥远的目标：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1.锻炼身体&lt;/span&gt;。最近越来越感觉到健康是福，所以10年，锻炼身体要放在第一的位置上，在这条里，给自己加上一点，少玩游戏。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2.看两本书，研究两个oracle专题，详细研究10个重要的动态性能视图。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3。去一个没有去过的地方。&lt;/span&gt;新疆，我很向往秋天的新疆。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;4.两年计划的第一年，为自己攒点什么，包括知识，金钱和沉淀。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;5.试着理财，试着淡然，试着成熟起来。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;6.继续学好英语，至于摄影，随着兴趣来吧。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;我想11年，新年伊始的时候，我可以看着这篇文章回想起10年走过的日子，然后对自己说一句：你是好样的，10年，你没有白活。&lt;/p&gt;</content><thr:total>0</thr:total><description>09年是轮回的一年，这一年是我的本命年，发生了很多很多的事，工作的，生活的，开心的，不开心的，一件件在脑中晃过，无论开心与否，无论痛苦与否，都已飘然远去，消散在自己背后的影子里。宠辱不惊，看庭前花开花落；去留无意，望天空云卷云舒。这是何等的一种心境，而我要做的就是努力看齐。&amp;#8212;&amp;#8211[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/01/2010'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794222/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/2010&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794222/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794222/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;09年是轮回的一年，这一年是我的本命年，发生了很多很多的事，工作的，生活的，开心的，不开心的，一件件在脑中晃过，无论开心与否，无论痛苦与否，都已飘然远去，消散在自己背后的影子里。宠辱不惊，看庭前花开花落；去留无意，望天空云卷云舒。这是何等的一种心境，而我要做的就是努力看齐。&amp;#8212;&amp;#8211;这句是写给2010年自己的话。&lt;/p&gt;
&lt;p&gt;两个轮回了，一切又回到了原点。掐指算来，人生能干点什么，或者有意义的时间也大约就那么3个轮回，对于我来说，就是从2010开始的后三个轮回，区区36年而已，抛去吃喝拉撒玩乐，能认真干些什么事的时间算一个轮回吧，12年。&lt;/p&gt;
&lt;p&gt;加油吧，或迷茫，或疯狂，或瞎忙的孩子们！&lt;/p&gt;
&lt;p&gt;07年底的时候写过一篇&lt;a href=&quot;http://www.dbadoc.com/2007/12/1227&quot; target=&quot;_blank&quot;&gt;年终总结&lt;/a&gt;，08年底的时候也写过一篇&lt;a href=&quot;http://www.dbadoc.com/2009/01/1018&quot; target=&quot;_blank&quot;&gt;年终总结&lt;/a&gt;。当初计划的09年要做的几件事：&lt;/p&gt;
&lt;p&gt;1。申请一个个人技术站点。&lt;/p&gt;
&lt;p&gt;2。读2本Oracle图书，看两篇Oracle文挡，研究两个Oracle专题。&lt;/p&gt;
&lt;p&gt;3。去一个没有去过的地方。&lt;/p&gt;
&lt;p&gt;4。锻炼身体。&lt;/p&gt;
&lt;p&gt;5。学好英文。&lt;/p&gt;
&lt;p&gt;6。买一个镜头，拍一些自己满意的照片。&lt;/p&gt;
&lt;p&gt;比较欣慰的是，现在看来，这些计划也大都完成了：&lt;/p&gt;
&lt;p&gt;1。09年年初的时候，建立了这个技术站点，钱倒是没花多少，不过话费了很多的时间，一点一点亲手把他建立起来的，从申请域名，到找空间，到安装wordpress，再到第一篇文章，虽然他并没有比那些第三方的博客好用多少，但是，不亲自去弄，就不知道这其中的辛苦与快乐！这种快乐是不亲自去尝试的人永远也不会体会到的。&lt;/p&gt;
&lt;p&gt;值得一提的是：&lt;span style=&quot;color: #000000;&quot;&gt;还为了一个人，一点一点的建立了另外一个&lt;/span&gt;&lt;strong&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;&lt;a href=&quot;http://www.wobusu.com/&quot; target=&quot;_blank&quot;&gt;站点&lt;/a&gt;&lt;/span&gt;&lt;/strong&gt;，付出了全部的真情和心血，家里没有网，去网吧一点一点的弄起来，什么都追求尽量做到最好，比我自己的站点付出了更多更多的精力。付出了很多，并不见得有人真正在乎你的付出，你含辛茹苦的付出，也许只被别人不屑的弃之一旁，剩下的也徒有伤悲之人。往事如梭，不提也罢，不过这个站点，我想我会一直保留下去，那也是一段真情和一段真心的见证吧。&lt;/p&gt;
&lt;p&gt;2。总体来说做的不是很好，书断断续续的看了两个半本，加起来估计都不到一本，回首看看，自己这一年在专业技术上的进步实在有限，也许是本命年人变的很浮躁，也许是放了很多的精力在别的事情上面，言而总之，总而言之，这浮躁的本命年已经过去，10年，我会好好努力加油的，多研究自己本职技术，其他的都是虚的，只有这些才是自己的，谁也抢不走。&lt;/p&gt;
&lt;p&gt;3。去一个没有去过的地方，应该是没有完成，本意是想去一个没有去过的地方旅游，比如西双版纳，比如海南，又比如世界上某个神奇的角落，可是小的地方也去了几个，比如去了天津，去了长城，新的一年，我应该多走走，多看看，人这一辈子不长，能去的地方也实在有限，何不乘着年轻，多走走呢？&lt;/p&gt;
&lt;p&gt;4。比较欣慰又比较无奈自己的就是这锻炼身体了，年初时，雄心勃勃，办了全年的游泳卡，自己想的，一定可以坚持游一年，刚开始，却也坚持了，感觉身体也确实好了些，自己能感觉得到，后来，各种原因，各种借口让自己的游泳计划在坚持了5个月之后没有坚持下去。现在，天异常的冷，专家说是又一个冰河世纪到来了，想想去游泳就很冷，自己对自己唯一的一个期许就是年前能再去游泳馆一次，哪怕看看也行。&lt;/p&gt;
&lt;p&gt;5，6，英文还是没有多少进步，看了一些英文电影，不看字幕虽然也大概能听懂，但感觉反应却总是滞后剧情的发展，看了些走遍美国，还一直发给某人看，说学好英文，可惜的是我们都没有坚持学下去吧。至于摄影拍照片，唯一想说的是当兴趣遇到烧钱，我也许只能举着我的小痰盂一直拍下去了。镜头也许暂时不会买了，因为本命年，我烧了很多的钱在其他方面，很傻很傻。&lt;/p&gt;
&lt;p&gt;无论乐意与否，无论坦然与否，09年，本命年都已经成为历史，永久的历史。人要向前看，在10年还不太晚的开头上，依然给自己定几个不太遥远的目标：&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;1.锻炼身体&lt;/span&gt;。最近越来越感觉到健康是福，所以10年，锻炼身体要放在第一的位置上，在这条里，给自己加上一点，少玩游戏。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;2.看两本书，研究两个oracle专题，详细研究10个重要的动态性能视图。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;3。去一个没有去过的地方。&lt;/span&gt;新疆，我很向往秋天的新疆。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;4.两年计划的第一年，为自己攒点什么，包括知识，金钱和沉淀。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;5.试着理财，试着淡然，试着成熟起来。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;6.继续学好英语，至于摄影，随着兴趣来吧。&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;我想11年，新年伊始的时候，我可以看着这篇文章回想起10年走过的日子，然后对自己说一句：你是好样的，10年，你没有白活。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794222/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/2010&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794222/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794222/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">性情人生</category><category domain="http://www.dbadoc.com">2010</category><category domain="http://www.dbadoc.com">总结</category><pubDate>Tue, 12 Jan 2010 14:59:31 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2037</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/01/2010</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794222/5445352</fs:itemid></item><item><title>Oracle 不使用索引，索引失效的几种情况</title><link atom:type="text/html">http://www.dbadoc.com/2010/01/oracle_index_not_use</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2033</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/01/oracle_index_not_use">&lt;p&gt;1,&amp;lt;&amp;gt;&lt;br /&gt;
2,单独的&amp;gt;,&amp;lt;,(有时会用到，有时不会)&lt;br /&gt;
3,like &amp;#8220;%_&amp;#8221; 百分号在前.&lt;br /&gt;
4,表没分析.&lt;br /&gt;
5,单独引用复合索引里非第一位置的索引列.&lt;br /&gt;
6,字符型字段为数字时在where条件里不添加引号.&lt;br /&gt;
7,对索引列进行运算.需要建立函数索引.&lt;br /&gt;
8,not in ,not exist.&lt;br /&gt;
9,当变量采用的是times变量，而表的字段采用的是date变量时.或相反情况。&lt;br /&gt;
10, 索引失效。&lt;br /&gt;
11,基于cost成本分析(oracle因为走全表成本会更小)：查询小表,或者返回值大概在10%以上&lt;br /&gt;
12,有时都考虑到了 但就是不走索引,drop了从建试试在&lt;br /&gt;
13,B-tree索引 is null不会走,is not null会走,位图索引 is null,is not null  都会走&lt;br /&gt;
14,联合索引 is not null 只要在建立的索引列（不分先后）都会走,&lt;br /&gt;
in null时  必须要和建立索引第一列一起使用,当建立索引第一位置条件是is null 时,其他建立索引的列可以是is null（但必须在所有列都满足is null的时候）,或者=一个值；&lt;br /&gt;
当建立索引的第一位置是=一个值时,其他索引列可以是任何情况（包括is null =一个值）,以上两种情况索引都会走。其他情况不会走。&lt;/p&gt;</content><thr:total>0</thr:total><description>1,&amp;#60;&amp;#62;
2,单独的&amp;#62;,&amp;#60;,(有时会用到，有时不会)
3,like &amp;#8220;%_&amp;#8221; 百分号在前.
4,表没分析.
5,单独引用复合索引里非第一位置的索引列.
6,字符型字段为数字时在where条件里不添加引号.
7,对索引列进行运算.需要建立函数索引.
8,[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/01/oracle_index_not_use'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794223/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/oracle_index_not_use&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794223/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794223/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;1,&amp;lt;&amp;gt;&lt;br /&gt;
2,单独的&amp;gt;,&amp;lt;,(有时会用到，有时不会)&lt;br /&gt;
3,like &amp;#8220;%_&amp;#8221; 百分号在前.&lt;br /&gt;
4,表没分析.&lt;br /&gt;
5,单独引用复合索引里非第一位置的索引列.&lt;br /&gt;
6,字符型字段为数字时在where条件里不添加引号.&lt;br /&gt;
7,对索引列进行运算.需要建立函数索引.&lt;br /&gt;
8,not in ,not exist.&lt;br /&gt;
9,当变量采用的是times变量，而表的字段采用的是date变量时.或相反情况。&lt;br /&gt;
10, 索引失效。&lt;br /&gt;
11,基于cost成本分析(oracle因为走全表成本会更小)：查询小表,或者返回值大概在10%以上&lt;br /&gt;
12,有时都考虑到了 但就是不走索引,drop了从建试试在&lt;br /&gt;
13,B-tree索引 is null不会走,is not null会走,位图索引 is null,is not null  都会走&lt;br /&gt;
14,联合索引 is not null 只要在建立的索引列（不分先后）都会走,&lt;br /&gt;
in null时  必须要和建立索引第一列一起使用,当建立索引第一位置条件是is null 时,其他建立索引的列可以是is null（但必须在所有列都满足is null的时候）,或者=一个值；&lt;br /&gt;
当建立索引的第一位置是=一个值时,其他索引列可以是任何情况（包括is null =一个值）,以上两种情况索引都会走。其他情况不会走。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794223/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/oracle_index_not_use&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794223/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794223/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">Oracle</category><category domain="http://www.dbadoc.com">index</category><pubDate>Fri, 08 Jan 2010 10:27:28 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2033</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/01/oracle_index_not_use</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794223/5445352</fs:itemid></item><item><title>db_block_checksum &amp;amp; db_block_checking</title><link atom:type="text/html">http://www.dbadoc.com/2010/01/db_block_checksum-db_block_checking</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2031</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/01/db_block_checksum-db_block_checking">&lt;p&gt;原文见：&lt;a href=&quot;http://bitirainy.itpub.net/post/330/4216&quot; target=&quot;_blank&quot;&gt;http://bitirainy.itpub.net/post/330/4216&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这两个参数的含义经常让人混淆，虽然都是对block进行检查。&lt;/p&gt;
&lt;p&gt;db_block_checksum 是在将数据块写到数据文件的时候对block内数据做一个校验写在块头，当读入时候重新计算校验和写出时候的校验对比，如果不同则认为是块损坏。这通常应 该是由于脱离oracle以外在os或者硬件中出现了损坏，如果设置为false则只对系统表空间有效。从8i开始设置为true的时候也同时对log block进行校验。&lt;/p&gt;
&lt;p&gt;db_block_checking 是当block发生任何变化的时候进行逻辑上的完整性和正确性检查，这在内存中进行，当发现错误就立即回退，设置为false则只对系统表空间有效。&lt;/p&gt;
&lt;p&gt;这 意味着，如果db_block_checking = false ,非系统表空间中数据在逻辑上可能已经损坏，但是 db_block_checksum 却是无法检查出来的，原样写到磁盘原样读到内存，因为它只校验块在写出后和读入之间是否发生变化而不检查写出前是否存在 逻辑上的正确。&lt;/p&gt;
&lt;p&gt;比如有时索引块损坏，造成通过索引无法获得数据，但是读索引块的时候并没有出1578错误，可能就是这个原因&lt;/p&gt;</content><thr:total>0</thr:total><description>原文见：&lt;a href=&quot;http://bitirainy.itpub.net/post/330/4216&quot; target=&quot;_blank&quot;&gt;http://bitirainy.itpub.net/post/330/4216&lt;/a&gt;
这两个参数的含义经常让人混淆，虽然都是对block进行检查。
db_block_checksum 是在将数据块写到数据文件的时候对block内数据做一个校验写在块头，当读入时候重新计算校验和写出时候的校验对比，[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/01/db_block_checksum-db_block_checking'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794224/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/db_block_checksum-db_block_checking&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794224/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794224/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;原文见：&lt;a href=&quot;http://bitirainy.itpub.net/post/330/4216&quot; target=&quot;_blank&quot;&gt;http://bitirainy.itpub.net/post/330/4216&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这两个参数的含义经常让人混淆，虽然都是对block进行检查。&lt;/p&gt;
&lt;p&gt;db_block_checksum 是在将数据块写到数据文件的时候对block内数据做一个校验写在块头，当读入时候重新计算校验和写出时候的校验对比，如果不同则认为是块损坏。这通常应 该是由于脱离oracle以外在os或者硬件中出现了损坏，如果设置为false则只对系统表空间有效。从8i开始设置为true的时候也同时对log block进行校验。&lt;/p&gt;
&lt;p&gt;db_block_checking 是当block发生任何变化的时候进行逻辑上的完整性和正确性检查，这在内存中进行，当发现错误就立即回退，设置为false则只对系统表空间有效。&lt;/p&gt;
&lt;p&gt;这 意味着，如果db_block_checking = false ,非系统表空间中数据在逻辑上可能已经损坏，但是 db_block_checksum 却是无法检查出来的，原样写到磁盘原样读到内存，因为它只校验块在写出后和读入之间是否发生变化而不检查写出前是否存在 逻辑上的正确。&lt;/p&gt;
&lt;p&gt;比如有时索引块损坏，造成通过索引无法获得数据，但是读索引块的时候并没有出1578错误，可能就是这个原因&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794224/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/db_block_checksum-db_block_checking&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794224/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794224/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">Oracle</category><category domain="http://www.dbadoc.com">db_block_checking</category><category domain="http://www.dbadoc.com">db_block_checksum</category><pubDate>Wed, 06 Jan 2010 15:19:47 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2031</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/01/db_block_checksum-db_block_checking</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794224/5445352</fs:itemid></item><item><title>监控索引是否使用过</title><link atom:type="text/html">http://www.dbadoc.com/2010/01/monitoring_index_usage</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2029</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2010/01/monitoring_index_usage">&lt;p&gt;在oracle 9i之后的版版本中可以使用以下语句来监控一个索引是否被使用过，这个特性为监控索引的使用，合理的调整表上的索引提供了方法，可以监控那些从来不使用的索引然后考虑删除或者重建。&lt;/p&gt;
&lt;p&gt;1.使用alter index index_name monitoring usage;来打个摸个索引的使用监控。当然你不想监控索引的使用时，可以使用如下语句来关掉它：alter index index_name nomonitoring usage;&lt;/p&gt;
&lt;p&gt;2.从v$object_usage视图中可以监控到这个索引是否被使用过，你可能期望 USAGE 字段是一个数字值，这样你就可以知道索引被使用的次数，但不幸的是，它的取值只为YES 或NO。即便如此，这个特性对于定位和删除不必要的索引页提供了帮助。&lt;/p&gt;
&lt;p&gt;set pages 999&lt;/p&gt;
&lt;p&gt;set heading off&lt;/p&gt;
&lt;p&gt;spool run_mon.sql&lt;/p&gt;
&lt;p&gt;select　 &amp;#8216;alter index &amp;#8216;  index_name   &amp;#8216; monitoring usage;&amp;#8217;　from dba_indexes  where owner not in (&amp;#8216;SYS&amp;#8217;,'SYSTEM&amp;#8217;,'PERFSTAT&amp;#8217;,'DBSNMP&amp;#8217;,'OUTLN&amp;#8217;,'WMSYS&amp;#8217;,'XDB&amp;#8217;,'ORDSYS&amp;#8217;,'CTXSYS&amp;#8217;,'MDSYS&amp;#8217;,'ANONYMOUS&amp;#8217;);&lt;/p&gt;
&lt;p&gt;spool off&lt;/p&gt;
&lt;p&gt;@run_mon&lt;/p&gt;</content><thr:total>0</thr:total><description>在oracle 9i之后的版版本中可以使用以下语句来监控一个索引是否被使用过，这个特性为监控索引的使用，合理的调整表上的索引提供了方法，可以监控那些从来不使用的索引然后考虑删除或者重建。
1.使用alter index index_name monitoring usage;来打个摸个索引的使用监控[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2010/01/monitoring_index_usage'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794225/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/monitoring_index_usage&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794225/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794225/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;在oracle 9i之后的版版本中可以使用以下语句来监控一个索引是否被使用过，这个特性为监控索引的使用，合理的调整表上的索引提供了方法，可以监控那些从来不使用的索引然后考虑删除或者重建。&lt;/p&gt;
&lt;p&gt;1.使用alter index index_name monitoring usage;来打个摸个索引的使用监控。当然你不想监控索引的使用时，可以使用如下语句来关掉它：alter index index_name nomonitoring usage;&lt;/p&gt;
&lt;p&gt;2.从v$object_usage视图中可以监控到这个索引是否被使用过，你可能期望 USAGE 字段是一个数字值，这样你就可以知道索引被使用的次数，但不幸的是，它的取值只为YES 或NO。即便如此，这个特性对于定位和删除不必要的索引页提供了帮助。&lt;/p&gt;
&lt;p&gt;set pages 999&lt;/p&gt;
&lt;p&gt;set heading off&lt;/p&gt;
&lt;p&gt;spool run_mon.sql&lt;/p&gt;
&lt;p&gt;select　 &amp;#8216;alter index &amp;#8216;  index_name   &amp;#8216; monitoring usage;&amp;#8217;　from dba_indexes  where owner not in (&amp;#8216;SYS&amp;#8217;,'SYSTEM&amp;#8217;,'PERFSTAT&amp;#8217;,'DBSNMP&amp;#8217;,'OUTLN&amp;#8217;,'WMSYS&amp;#8217;,'XDB&amp;#8217;,'ORDSYS&amp;#8217;,'CTXSYS&amp;#8217;,'MDSYS&amp;#8217;,'ANONYMOUS&amp;#8217;);&lt;/p&gt;
&lt;p&gt;spool off&lt;/p&gt;
&lt;p&gt;@run_mon&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794225/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2010/01/monitoring_index_usage&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794225/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794225/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">Oracle</category><category domain="http://www.dbadoc.com">index</category><category domain="http://www.dbadoc.com">monitoring</category><pubDate>Wed, 06 Jan 2010 10:07:38 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2029</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2010/01/monitoring_index_usage</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794225/5445352</fs:itemid></item><item><title>元旦快乐！</title><link atom:type="text/html">http://www.dbadoc.com/2009/12/happy_new_year_2</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2027</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2009/12/happy_new_year_2">&lt;p&gt;09年，本命年，不平凡的一年，发生了很多故事的一年，马上就要从眼前溜走了，一切高兴的，不高兴的，愉快的，痛苦的事都留在09年吧，新的一年，我们有新的希望。加油！自己的10年，两年计划中的第一年，也是最重要的一年，加油加油！&lt;/p&gt;
&lt;p&gt;今天要加班，跨年加班，最近也比较烦，所以09年的年终总结和10年的展望改天再写。&lt;/p&gt;</content><thr:total>0</thr:total><description>09年，本命年，不平凡的一年，发生了很多故事的一年，马上就要从眼前溜走了，一切高兴的，不高兴的，愉快的，痛苦的事都留在09年吧，新的一年，我们有新的希望。加油！自己的10年，两年计划中的第一年，也是最重要的一年，加油加油！
今天要加班，跨年加班，最近也比较烦，所以09年的年终总结和10年的展望改天再[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2009/12/happy_new_year_2'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794226/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2009/12/happy_new_year_2&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794226/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794226/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;09年，本命年，不平凡的一年，发生了很多故事的一年，马上就要从眼前溜走了，一切高兴的，不高兴的，愉快的，痛苦的事都留在09年吧，新的一年，我们有新的希望。加油！自己的10年，两年计划中的第一年，也是最重要的一年，加油加油！&lt;/p&gt;
&lt;p&gt;今天要加班，跨年加班，最近也比较烦，所以09年的年终总结和10年的展望改天再写。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794226/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2009/12/happy_new_year_2&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794226/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794226/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">闲扯</category><category domain="http://www.dbadoc.com">元旦快乐</category><pubDate>Thu, 31 Dec 2009 16:03:10 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2027</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2009/12/happy_new_year_2</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794226/5445352</fs:itemid></item><item><title>我的数据库学习“曲线”&amp;#8212;-牛新庄 (zt)</title><link atom:type="text/html">http://www.dbadoc.com/2009/12/niuxinzhuang_database</link><author xmlns="http://www.w3.org/2005/Atom"><name>Baallord</name><uri>http://www.dbadoc.com</uri></author><id xmlns="http://www.w3.org/2005/Atom">http://www.dbadoc.com/?p=2025</id><content xmlns="http://www.w3.org/2005/Atom" type="html" xml:base="http://www.dbadoc.com/2009/12/niuxinzhuang_database">&lt;p&gt;编者按：牛新庄，数据库维护、优化和架构专家；曾获得国内数据库领域最高荣誉——“2006年中国首届杰出数据库工程师”；数年前曾被IBM全球软件部以年薪60万元人民币聘用，而他却婉然拒绝。这样一个躲藏在幕后的“牛人”，有着怎样的学习、发展之路？为此，本刊特邀牛新庄博士，请他讲述一个真实版的“数据库之路”。&lt;/p&gt;
&lt;p&gt;选定发展方向&lt;br /&gt;
1999年，我在开始读研时就给自己确定了以后的发展方向。&lt;br /&gt;
当时有两个方向：网络，数据库技术。因为在2000年之时，网络大热，市场上拥有CCNP、CCIE证书的人特别牛。所以我当时也考下了CCNP证书，但后来发现网络方向涉及很多硬件层面的东西，这些都对厂商的依赖性太强，个人发挥空间不大。而我喜欢钻研，所以慢慢开始转向专攻数据库技术。&lt;br /&gt;
在认准数据库这个方向后，我开始深入学习数据库理论方面的知识。当时，人大王珊教授的《数据库系统原理教程》一书，我读了几十遍。在学习数据库理论的同时，我开始接触并深入学习DB2和Oracle，并从1999年开始使用DB2 V5.2。那时，市场上关于DB2方面的技术书籍几乎没有，互联网也不像现在这么发达。因为我的导师做一个课题需要用到DB2数据库，但是我只能依靠查看 DB2随机文档来学习。那时，我还自己兼职，通过帮别人做些小软件赚钱，外加课题经费，以支付考OCP认证和DB2认证的费用。&lt;br /&gt;
到现在为止，我一直认为考认证是一个很好的学习动力。因为考试费用不菲，如果不想浪费钱只能拼命看书。我在读研的2000年就通过了OCP 8i认证，后来又陆续通过DB2 V5.2认证。这些认证极大地增强了我的自信。同时，在帮助导师用PB、Delphi等编程工具做应用开发时，我有意识地增强对SQL的学习，这对我后来的性能调优工作非常有帮助。&lt;br /&gt;
这里我想说的是，做好一个时期的人生规划非常重要。我们首先要有一个明确的努力方向和规划，然后有意识的往这个方向努力。这种积极主动的学习要比被动学习效率高很多。&lt;/p&gt;
&lt;p&gt;第一次做培训&lt;br /&gt;
“机遇偏爱于有准备的头脑”，这句话虽是老生常谈，却是人生真谛。记得2000年底，我在网上看到一个帖子说需要一个人去安装DB2数据库，差旅报销，每天500元，我喜出望外。因为这项工作需要有DB2认证才能去，而我那时DB2高级系统管理和应用开发的认证都有，所以很快就通过了对方的审核。但是当我到客户现场时才发现，不是安装DB2而是要给客户讲课，当时我就傻眼了，因为讲课需要的知识远比安装配置数据库要难得多，更何况我之前根本没有讲过课。没办法，压力也是动力，只能前一天夜里看教材备课到凌晨5点。短短睡了两个小时后，8点半去讲课。四天讲课下来，我总共休息了12个小时。还好自己毕竟有 DB2应用开发经验和DB2认证做基础，总算勉强应付了过去。只是没想到的是，这次并不算顺利的培训，竟是我未来几年培训生涯的开始。&lt;/p&gt;
&lt;p&gt;将培训当学习的动力&lt;br /&gt;
经过第一次讲课后，我看到了自己的差距，知道仅有认证是不够的。客户的很多问题，书本上没有答案，需要自己在实践经验上做努力。另外，讲课前讲师需要把一些原理、概念性的东西弄清楚，也需要对数据库进行深入学习。&lt;br /&gt;
后来，IBM培训部通过一些渠道知道我能讲DB2且拥有相关证书，就找我讲授DB2系列课程。所以，从2001年开始，我就经常作为IBM官方讲师讲授 DB2系列的所有课程。我自认为讲课是一个很好的学习过程，因为课前要深入了解概念，对于自己的理论深入学习有很大帮助。同时，课堂上学员的实际操作问题也会强迫自己做更深入的研究。&lt;br /&gt;
我对培训有这样的认识：学员听你讲三个小时，要远远胜过自己看3小时的书。如果把一堂课的内容比喻成一杯水，那老师至少应该提前储备一桶水。所以，在讲课之前，我精心准备实验，深入和学员交流。我讲课从不照本宣科，而是自己准备了很多教材外比较实用的知识来扩展教材内容。同时争取上课过程中把一些概念用浅显易懂的例子来讲解。要想做到这些，首先自己必须对这个概念有深刻的理解才行，这一切都在客观上促进了自己的学习。&lt;br /&gt;
随着培训的增多，有部分客户开始找我做实际的调优工作。记得我第一次去为客户现场调优是2001年，去大连大通证券解决锁等待问题。客户环境用的是AIX 和CICS。当时虽然问题解决了，但自己心里还是比较虚，因为对AIX和CICS不了解，万一是这两个方面有问题，自己就没办法搞定了；这让我认识到一个复杂系统的调整往往需要具备多方面的知识。这件事之后，我在网上买了一个140的IBM工作站小机，自己安装AIX并开始学习。&lt;/p&gt;
&lt;p&gt;数据库学习Tips&lt;br /&gt;
根据我对数据库的理解，目前市场上虽然有Oracle，DB2，Informix，Sybase和SQL Server数据库，但Informix数据库已经被IBM收购，而Sybase数据库在技术和市场上正走向没落，占据市场主要份额的就是 Oracle，DB2和SQL Server数据库。SQL Server数据库非常好，但是很遗憾的是只能在Windows平台使用。所以如果你深入研究SQL Server数据库，我只能说获取高薪的概率稍低，而且坦白的说，使用SQL Sever数据库的企业一般是中小企业居多。而国内做Oracle数据库的人太多，如果你想在Oracle领域出人头地，难度极大。但是，做DB2数据库的人反而不太多，物以稀为贵。况且，DB2数据库广泛应用在银行、电信、制造行业、零售行业、保险行业等“高薪”领域中，所以我强烈建议学习DB2数据库，做IBM技术一般获取高薪的概率相对会大一些。我们的时间精力是有限的，所以必须选择好方向然后努力为之。除了SQL Server，这几个数据库我都在使用，我个人感觉除了功能外，对于运行稳定而言，相对于Oracle不太稳定的优化器，DB2无疑是最稳定的，它的优化器无比强大。如果能在锁方面再有更先进的技术，那么DB2将是完美的。&lt;/p&gt;
&lt;p&gt;这期间，我一边学习，一边通过了AIX的全部认证。记得非常清楚的是，为了做HA的实验，我花费了很大工夫。因为那时小型机不像今天这么普及，无法搞到7133阵列。后来我又学习了CICS、WebSphere、MQ和存储。就这样，在我培训的过程中，发现自己哪方面薄弱并且感觉这个方向有前途，我就会开始学习。不过，那时我的技术主要还是围绕IBM产品为主。由于自己对培训比较用心且颇受客户好评，找我做培训的国内培训机构开始变多。这个期间我自己的技术水平也增长很快。&lt;br /&gt;
2002年11月，我参加了首届 “IBM DeveloperWorksLive! China 2002”大会，并获得IBM首次在国内评选的“杰出软件技术专家”奖，当时在6名获奖者中名列第2。这个奖项客观上对我在客户群的拓展方面起到很大帮助。找我解决问题的人更多了，所以2002—2003年也成了我技术提升最快的两年。&lt;br /&gt;
这两年内，我陆续学习了HP-UX、WebSphere和MQ并通过认证。我自己的感觉是，如果你把一门技术研究得非常深、非常透，由于触类旁通的缘故，再去学习另一门技术时就很轻松。所以，我在学完AIX再去学习HP-UX时，感觉非常轻松。同样，在学习ORACLE和DB2后再去学习Informix 也同样很容易。通过这种纵向的深入和横向的比较，各种产品的所长所短也会非常清楚，自己的技术视野无意间更加全面化。而且通过对一个产品的深入，你往往能够发现这个产品的缺点和需要改进的地方。就拿DB2来说，每次版本更新的新特性,在新版本未上市前我就可以猜得差不多了。这主要有三个原因：一是我贴近真实用户，了解他们的真正需求；二是自己一直在用且不断总结思考；三是这些特性别的数据库有，而DB2没有，那在下个版本就会增加。所以相对来说，我自身对新版本的新特性学习就非常轻松了。就DB2而言，我拥有DB2 V5.2 、V7.1、V8.1和DB2 V9的全部认证，而且我应该是国内第一个把DB2 V8认证全部通过的人，当然，这其中也有巧合的成分。&lt;br /&gt;
重要的一点是：学习过程中，要不断地把实践和理论融合，知其然更知其所以然，这样提升就会快很多。&lt;/p&gt;
&lt;p&gt;现场救援“赶场”记&lt;br /&gt;
2004—2005年是我最忙碌的两年，那时候找我讲课的培训机构和需要性能调优的客户非常多，基本上整天在天上飞。培训机构找我讲课常常需要提前一个月预约。那两年内，除了过年几天，其他时间都是在做培训和诊断、调优，足迹遍及国内主要城市。我自己基本上是国内六大银行开发中心和数据中心培训的指定讲师，并为北京银信科技、山东农信、广东农信，交行大集中IBP等项目做数据库技术顾问。&lt;br /&gt;
那时的我年轻、精力充沛。记得最刺激的一次是2004年9月的一天，上午9点为上海移动IT部门做AIX动态逻辑分区（DLPAR）培训，结束时是17 点。之后，立刻坐出租车前往扬州，于20点到达扬州供电局并协助他们进行电力负荷控制系统项目上线，一直奋战到凌晨3点半。接着，又连夜乘出租车赶往上海，在凌晨6点到达酒店。休息两小时后，8点出发，准时出现在上海移动培训现场。那时我对报酬不太在意，想的主要是用心积累技术经验和客户资源。在我看来，能够不断通过实践让自己成长是第一要义。而且，去的客户现场越多，处理的问题就越多，也就越多地发现自己的不足，然后再拼命学习，不断积累、总结和思考，进入了一个良性循环。&lt;br /&gt;
至今我仍然怀念那段充实、紧张而充满激情的光辉岁月。2004年和2005年，一方面因为以独立咨询顾问的个人身份无法出具发票；另一方面，项目越做越大，尤其是很多银行的数据库架构和维护项目涉及合同金额也越来越大，需要签订正式公司合同。于是，我就分别在上海、北京注册了公司。当然这些年我并非都是一帆风顺，也犯过一些重大错误，例如：我曾经在2002年5月1日把海南美兰机场的数据库调死，导致机场航班信息管理系统瘫痪。早期也曾经因为调整某证券系统宕机而影响股民交易，这些都对客户造成了影响，但这些都是成长必须要走的路。经过这两次事件后，我自己也思考、总结了很多，在之后的调优工作中我基本上再没有犯过错误。&lt;/p&gt;
&lt;p&gt;我的秘诀：学习、积累、规划&lt;br /&gt;
2006年8月我获得“2006年中国首届杰出数据库工程师”称号，算是对我多年学习数据库的一个总结。自2007年开始，我专注于做一些大客户的运维工作，并相应减少了培训次数。2008年，我被建设银行以年薪217万聘请为资深技术专家来维护Oracle和Informix数据库。就做技术而言，以一己之力能挣到年薪几百万常常令我感到自豪，也让我感受到技术的魅力，觉得自己多年来对技术的钻研得到了认可。&lt;br /&gt;
之所以讲述我的技术之路，主要目的是给大家一些参考，尽可能多地去了解社会的需求，有意识给自己制定人生规划。我自己认为，多年来能取得这样的成绩，勤奋、努力和坚持一直是我最看重的。因为有了这些，才不至于当机遇光顾时，你却不知所措。&lt;br /&gt;
现在很多年轻人，恰恰缺少的就是这样的忘我与痴迷，在我熟悉的数据库技术领域，很多年轻人越来越早地将注意力集中在薪水和职位上，这是很不明智的行为。其实，往往那些将诸如高薪与职位忘怀的人反而能更快地取得成功。“不经一番寒彻骨，安得梅花扑鼻香？”这样的道理人人都懂，可能够真正去实践的人却并不多。结合我的学习经验与感悟，我总结有16字要诀：去除浮躁，认真学习，不断积累，寻找机遇。&lt;br /&gt;
最后，我用这句话与大家共勉：古之成大事者，不唯有超世之才，亦唯有坚韧不拔之志也！&lt;/p&gt;
&lt;p&gt;作者简介：&lt;br /&gt;
牛新庄博士，研究方向为数据仓库和数据挖掘。是IBM官方资深培训讲师（培训DB2,AIX,MQ,WebSphere和CICS）。2002年获IBM 杰出软件专家奖，2006年获“首届中国杰出数据库工程师奖”、“2006年IT168技术卓越奖”。是中信银行、山东农信、广东农信等公司资深技术顾问，中国建设银行总行特聘资深技术专家。拥有OCP，AIX，DB2，HP-UX，MQ，CICS和WebSphere等二十多项国际认证。著有《Oracle数据库开发讲座——Oracle9i Jdeveloper与J2EE实务应用》、《DB2应用开发实战指导》、《循序渐进DB2-系统管理、运行维护与应用案例》、《深入解析DB2-高级管理、内部体系结构与诊断案例》和《DB2性能调整与优化》等书。&lt;/p&gt;</content><thr:total>0</thr:total><description>编者按：牛新庄，数据库维护、优化和架构专家；曾获得国内数据库领域最高荣誉——“2006年中国首届杰出数据库工程师”；数年前曾被IBM全球软件部以年薪60万元人民币聘用，而他却婉然拒绝。这样一个躲藏在幕后的“牛人”，有着怎样的学习、发展之路？为此，本刊特邀牛新庄博士，请他讲述一个真实版的“数据库之路”[......]&lt;p class='read-more'&gt;&lt;a href='http://www.dbadoc.com/2009/12/niuxinzhuang_database'&gt;继续阅读&lt;/a&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794227/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2009/12/niuxinzhuang_database&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794227/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794227/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><content:encoded>&lt;p&gt;编者按：牛新庄，数据库维护、优化和架构专家；曾获得国内数据库领域最高荣誉——“2006年中国首届杰出数据库工程师”；数年前曾被IBM全球软件部以年薪60万元人民币聘用，而他却婉然拒绝。这样一个躲藏在幕后的“牛人”，有着怎样的学习、发展之路？为此，本刊特邀牛新庄博士，请他讲述一个真实版的“数据库之路”。&lt;/p&gt;
&lt;p&gt;选定发展方向&lt;br /&gt;
1999年，我在开始读研时就给自己确定了以后的发展方向。&lt;br /&gt;
当时有两个方向：网络，数据库技术。因为在2000年之时，网络大热，市场上拥有CCNP、CCIE证书的人特别牛。所以我当时也考下了CCNP证书，但后来发现网络方向涉及很多硬件层面的东西，这些都对厂商的依赖性太强，个人发挥空间不大。而我喜欢钻研，所以慢慢开始转向专攻数据库技术。&lt;br /&gt;
在认准数据库这个方向后，我开始深入学习数据库理论方面的知识。当时，人大王珊教授的《数据库系统原理教程》一书，我读了几十遍。在学习数据库理论的同时，我开始接触并深入学习DB2和Oracle，并从1999年开始使用DB2 V5.2。那时，市场上关于DB2方面的技术书籍几乎没有，互联网也不像现在这么发达。因为我的导师做一个课题需要用到DB2数据库，但是我只能依靠查看 DB2随机文档来学习。那时，我还自己兼职，通过帮别人做些小软件赚钱，外加课题经费，以支付考OCP认证和DB2认证的费用。&lt;br /&gt;
到现在为止，我一直认为考认证是一个很好的学习动力。因为考试费用不菲，如果不想浪费钱只能拼命看书。我在读研的2000年就通过了OCP 8i认证，后来又陆续通过DB2 V5.2认证。这些认证极大地增强了我的自信。同时，在帮助导师用PB、Delphi等编程工具做应用开发时，我有意识地增强对SQL的学习，这对我后来的性能调优工作非常有帮助。&lt;br /&gt;
这里我想说的是，做好一个时期的人生规划非常重要。我们首先要有一个明确的努力方向和规划，然后有意识的往这个方向努力。这种积极主动的学习要比被动学习效率高很多。&lt;/p&gt;
&lt;p&gt;第一次做培训&lt;br /&gt;
“机遇偏爱于有准备的头脑”，这句话虽是老生常谈，却是人生真谛。记得2000年底，我在网上看到一个帖子说需要一个人去安装DB2数据库，差旅报销，每天500元，我喜出望外。因为这项工作需要有DB2认证才能去，而我那时DB2高级系统管理和应用开发的认证都有，所以很快就通过了对方的审核。但是当我到客户现场时才发现，不是安装DB2而是要给客户讲课，当时我就傻眼了，因为讲课需要的知识远比安装配置数据库要难得多，更何况我之前根本没有讲过课。没办法，压力也是动力，只能前一天夜里看教材备课到凌晨5点。短短睡了两个小时后，8点半去讲课。四天讲课下来，我总共休息了12个小时。还好自己毕竟有 DB2应用开发经验和DB2认证做基础，总算勉强应付了过去。只是没想到的是，这次并不算顺利的培训，竟是我未来几年培训生涯的开始。&lt;/p&gt;
&lt;p&gt;将培训当学习的动力&lt;br /&gt;
经过第一次讲课后，我看到了自己的差距，知道仅有认证是不够的。客户的很多问题，书本上没有答案，需要自己在实践经验上做努力。另外，讲课前讲师需要把一些原理、概念性的东西弄清楚，也需要对数据库进行深入学习。&lt;br /&gt;
后来，IBM培训部通过一些渠道知道我能讲DB2且拥有相关证书，就找我讲授DB2系列课程。所以，从2001年开始，我就经常作为IBM官方讲师讲授 DB2系列的所有课程。我自认为讲课是一个很好的学习过程，因为课前要深入了解概念，对于自己的理论深入学习有很大帮助。同时，课堂上学员的实际操作问题也会强迫自己做更深入的研究。&lt;br /&gt;
我对培训有这样的认识：学员听你讲三个小时，要远远胜过自己看3小时的书。如果把一堂课的内容比喻成一杯水，那老师至少应该提前储备一桶水。所以，在讲课之前，我精心准备实验，深入和学员交流。我讲课从不照本宣科，而是自己准备了很多教材外比较实用的知识来扩展教材内容。同时争取上课过程中把一些概念用浅显易懂的例子来讲解。要想做到这些，首先自己必须对这个概念有深刻的理解才行，这一切都在客观上促进了自己的学习。&lt;br /&gt;
随着培训的增多，有部分客户开始找我做实际的调优工作。记得我第一次去为客户现场调优是2001年，去大连大通证券解决锁等待问题。客户环境用的是AIX 和CICS。当时虽然问题解决了，但自己心里还是比较虚，因为对AIX和CICS不了解，万一是这两个方面有问题，自己就没办法搞定了；这让我认识到一个复杂系统的调整往往需要具备多方面的知识。这件事之后，我在网上买了一个140的IBM工作站小机，自己安装AIX并开始学习。&lt;/p&gt;
&lt;p&gt;数据库学习Tips&lt;br /&gt;
根据我对数据库的理解，目前市场上虽然有Oracle，DB2，Informix，Sybase和SQL Server数据库，但Informix数据库已经被IBM收购，而Sybase数据库在技术和市场上正走向没落，占据市场主要份额的就是 Oracle，DB2和SQL Server数据库。SQL Server数据库非常好，但是很遗憾的是只能在Windows平台使用。所以如果你深入研究SQL Server数据库，我只能说获取高薪的概率稍低，而且坦白的说，使用SQL Sever数据库的企业一般是中小企业居多。而国内做Oracle数据库的人太多，如果你想在Oracle领域出人头地，难度极大。但是，做DB2数据库的人反而不太多，物以稀为贵。况且，DB2数据库广泛应用在银行、电信、制造行业、零售行业、保险行业等“高薪”领域中，所以我强烈建议学习DB2数据库，做IBM技术一般获取高薪的概率相对会大一些。我们的时间精力是有限的，所以必须选择好方向然后努力为之。除了SQL Server，这几个数据库我都在使用，我个人感觉除了功能外，对于运行稳定而言，相对于Oracle不太稳定的优化器，DB2无疑是最稳定的，它的优化器无比强大。如果能在锁方面再有更先进的技术，那么DB2将是完美的。&lt;/p&gt;
&lt;p&gt;这期间，我一边学习，一边通过了AIX的全部认证。记得非常清楚的是，为了做HA的实验，我花费了很大工夫。因为那时小型机不像今天这么普及，无法搞到7133阵列。后来我又学习了CICS、WebSphere、MQ和存储。就这样，在我培训的过程中，发现自己哪方面薄弱并且感觉这个方向有前途，我就会开始学习。不过，那时我的技术主要还是围绕IBM产品为主。由于自己对培训比较用心且颇受客户好评，找我做培训的国内培训机构开始变多。这个期间我自己的技术水平也增长很快。&lt;br /&gt;
2002年11月，我参加了首届 “IBM DeveloperWorksLive! China 2002”大会，并获得IBM首次在国内评选的“杰出软件技术专家”奖，当时在6名获奖者中名列第2。这个奖项客观上对我在客户群的拓展方面起到很大帮助。找我解决问题的人更多了，所以2002—2003年也成了我技术提升最快的两年。&lt;br /&gt;
这两年内，我陆续学习了HP-UX、WebSphere和MQ并通过认证。我自己的感觉是，如果你把一门技术研究得非常深、非常透，由于触类旁通的缘故，再去学习另一门技术时就很轻松。所以，我在学完AIX再去学习HP-UX时，感觉非常轻松。同样，在学习ORACLE和DB2后再去学习Informix 也同样很容易。通过这种纵向的深入和横向的比较，各种产品的所长所短也会非常清楚，自己的技术视野无意间更加全面化。而且通过对一个产品的深入，你往往能够发现这个产品的缺点和需要改进的地方。就拿DB2来说，每次版本更新的新特性,在新版本未上市前我就可以猜得差不多了。这主要有三个原因：一是我贴近真实用户，了解他们的真正需求；二是自己一直在用且不断总结思考；三是这些特性别的数据库有，而DB2没有，那在下个版本就会增加。所以相对来说，我自身对新版本的新特性学习就非常轻松了。就DB2而言，我拥有DB2 V5.2 、V7.1、V8.1和DB2 V9的全部认证，而且我应该是国内第一个把DB2 V8认证全部通过的人，当然，这其中也有巧合的成分。&lt;br /&gt;
重要的一点是：学习过程中，要不断地把实践和理论融合，知其然更知其所以然，这样提升就会快很多。&lt;/p&gt;
&lt;p&gt;现场救援“赶场”记&lt;br /&gt;
2004—2005年是我最忙碌的两年，那时候找我讲课的培训机构和需要性能调优的客户非常多，基本上整天在天上飞。培训机构找我讲课常常需要提前一个月预约。那两年内，除了过年几天，其他时间都是在做培训和诊断、调优，足迹遍及国内主要城市。我自己基本上是国内六大银行开发中心和数据中心培训的指定讲师，并为北京银信科技、山东农信、广东农信，交行大集中IBP等项目做数据库技术顾问。&lt;br /&gt;
那时的我年轻、精力充沛。记得最刺激的一次是2004年9月的一天，上午9点为上海移动IT部门做AIX动态逻辑分区（DLPAR）培训，结束时是17 点。之后，立刻坐出租车前往扬州，于20点到达扬州供电局并协助他们进行电力负荷控制系统项目上线，一直奋战到凌晨3点半。接着，又连夜乘出租车赶往上海，在凌晨6点到达酒店。休息两小时后，8点出发，准时出现在上海移动培训现场。那时我对报酬不太在意，想的主要是用心积累技术经验和客户资源。在我看来，能够不断通过实践让自己成长是第一要义。而且，去的客户现场越多，处理的问题就越多，也就越多地发现自己的不足，然后再拼命学习，不断积累、总结和思考，进入了一个良性循环。&lt;br /&gt;
至今我仍然怀念那段充实、紧张而充满激情的光辉岁月。2004年和2005年，一方面因为以独立咨询顾问的个人身份无法出具发票；另一方面，项目越做越大，尤其是很多银行的数据库架构和维护项目涉及合同金额也越来越大，需要签订正式公司合同。于是，我就分别在上海、北京注册了公司。当然这些年我并非都是一帆风顺，也犯过一些重大错误，例如：我曾经在2002年5月1日把海南美兰机场的数据库调死，导致机场航班信息管理系统瘫痪。早期也曾经因为调整某证券系统宕机而影响股民交易，这些都对客户造成了影响，但这些都是成长必须要走的路。经过这两次事件后，我自己也思考、总结了很多，在之后的调优工作中我基本上再没有犯过错误。&lt;/p&gt;
&lt;p&gt;我的秘诀：学习、积累、规划&lt;br /&gt;
2006年8月我获得“2006年中国首届杰出数据库工程师”称号，算是对我多年学习数据库的一个总结。自2007年开始，我专注于做一些大客户的运维工作，并相应减少了培训次数。2008年，我被建设银行以年薪217万聘请为资深技术专家来维护Oracle和Informix数据库。就做技术而言，以一己之力能挣到年薪几百万常常令我感到自豪，也让我感受到技术的魅力，觉得自己多年来对技术的钻研得到了认可。&lt;br /&gt;
之所以讲述我的技术之路，主要目的是给大家一些参考，尽可能多地去了解社会的需求，有意识给自己制定人生规划。我自己认为，多年来能取得这样的成绩，勤奋、努力和坚持一直是我最看重的。因为有了这些，才不至于当机遇光顾时，你却不知所措。&lt;br /&gt;
现在很多年轻人，恰恰缺少的就是这样的忘我与痴迷，在我熟悉的数据库技术领域，很多年轻人越来越早地将注意力集中在薪水和职位上，这是很不明智的行为。其实，往往那些将诸如高薪与职位忘怀的人反而能更快地取得成功。“不经一番寒彻骨，安得梅花扑鼻香？”这样的道理人人都懂，可能够真正去实践的人却并不多。结合我的学习经验与感悟，我总结有16字要诀：去除浮躁，认真学习，不断积累，寻找机遇。&lt;br /&gt;
最后，我用这句话与大家共勉：古之成大事者，不唯有超世之才，亦唯有坚韧不拔之志也！&lt;/p&gt;
&lt;p&gt;作者简介：&lt;br /&gt;
牛新庄博士，研究方向为数据仓库和数据挖掘。是IBM官方资深培训讲师（培训DB2,AIX,MQ,WebSphere和CICS）。2002年获IBM 杰出软件专家奖，2006年获“首届中国杰出数据库工程师奖”、“2006年IT168技术卓越奖”。是中信银行、山东农信、广东农信等公司资深技术顾问，中国建设银行总行特聘资深技术专家。拥有OCP，AIX，DB2，HP-UX，MQ，CICS和WebSphere等二十多项国际认证。著有《Oracle数据库开发讲座——Oracle9i Jdeveloper与J2EE实务应用》、《DB2应用开发实战指导》、《循序渐进DB2-系统管理、运行维护与应用案例》、《深入解析DB2-高级管理、内部体系结构与诊断案例》和《DB2性能调整与优化》等书。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/335794227/dbadoc/feedsky/s.gif?r=http://www.dbadoc.com/2009/12/niuxinzhuang_database&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/dbadoc/335794227/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/dbadoc/335794227/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><category domain="http://www.dbadoc.com">db2</category><category domain="http://www.dbadoc.com">数据库</category><category domain="http://www.dbadoc.com">牛新庄</category><pubDate>Mon, 28 Dec 2009 15:17:29 +0800</pubDate><guid isPermaLink="false">http://www.dbadoc.com/?p=2025</guid><dc:creator>Baallord</dc:creator><fs:srclink>http://www.dbadoc.com/2009/12/niuxinzhuang_database</fs:srclink><fs:srcfeed>http://www.dbadoc.com/feed/atom</fs:srcfeed><fs:itemid>feedsky/dbadoc/~7337887/335794227/5445352</fs:itemid></item></channel></rss>