Oracle连接方式和哈希连接

Oracle连接方式和哈希连接,oracle,oracle10g,nested-loops,hierarchical,Oracle,Oracle10g,Nested Loops,Hierarchical,我有一个问题1: select * from ( select 'null' parentcode, u.unititemcode childcode, null unititempartnbr, null partoid, null proccode, null unititemtype, null qualcat, null unititemgm2, null rsncode from wi_unititem u where u.prodproccode='PM11' and u.prode

我有一个问题1:

select *
from (
select 'null' parentcode, u.unititemcode childcode, null unititempartnbr, null partoid,
null proccode, null unititemtype, null qualcat, null unititemgm2, null rsncode
from wi_unititem u where
u.prodproccode='PM11' and
u.prodendtime>sysdate-10
union all
select p.unititemcode parentcode, u.unititemcode childcode, 0 unititempartnbr, p.oid partoid,
p.proccode, u.unititemtype, u.qualcat, u.unititemgm2, u.rsncode
from wi_uitempart p, wi_unititem u where
p.unititemparttype='USEDSET' and
u.prodproccode=p.proccode and
u.setid=p.setid    
) m
where m.unititemtype<>'SKID'
start with m.parentcode='null'
connect by prior m.childcode=m.parentcode
和问题2:

select *
from (
select 'null' parentcode, u.unititemcode childcode, null unititempartnbr, null partoid,
null proccode, null unititemtype, null qualcat, null unititemgm2, null rsncode
from wi_unititem u where
u.prodproccode='PM11' and
u.prodendtime>sysdate-20
union all
select p.unititemcode parentcode, u.unititemcode childcode, 0 unititempartnbr, p.oid partoid,
p.proccode, u.unititemtype, u.qualcat, u.unititemgm2, u.rsncode
from wi_uitempart p, wi_unititem u where
p.unititemparttype='USEDSET' and
u.prodproccode=p.proccode and
u.setid=p.setid    
) m
where m.unititemtype<>'SKID'
start with m.parentcode='null'
connect by prior m.childcode=m.parentcode
查询1包含“sysdate-10”,查询2包含“sysdate-20”,这是唯一的区别,查询1运行得非常快,查询2运行得非常慢

如果我们比较执行计划,那么可以在从14和16开始的行中找到差异: 查询1使用嵌套循环联接+索引范围扫描 查询2使用哈希联接+索引完全扫描


是否可以将查询1的执行计划也用于查询2?

复制执行计划的最简单方法是使用全套大纲提示

使用这两条语句生成包含大纲数据的解释计划。这也是生成解释计划的最佳方式,原因如下

使用大纲数据作为提示,以确保执行计划保持不变。虽然“保证”可能是一个强有力的词;这些未记录的提示可能无法在不同版本中工作,或者如果查询的语义不同

select 
  /*+
      BEGIN_OUTLINE_DATA
      FULL(@"SEL$1" "DUAL"@"SEL$1")
      OUTLINE_LEAF(@"SEL$1")
      ALL_ROWS
      DB_VERSION('12.1.0.2')
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
* from dual;

这应该管用,但有点难看。理想情况下,您希望找到Oracle做出错误决策的根本原因—调查估计基数与实际基数、统计数据等。但是有很多方法可以做到这一点,而且需要很长时间。作为一种折衷办法,您可能希望使用这些提示,并尝试将其缩小到修复性能问题所需的一两个提示。

复制执行计划的最简单方法是使用全套大纲提示

使用这两条语句生成包含大纲数据的解释计划。这也是生成解释计划的最佳方式,原因如下

使用大纲数据作为提示,以确保执行计划保持不变。虽然“保证”可能是一个强有力的词;这些未记录的提示可能无法在不同版本中工作,或者如果查询的语义不同

select 
  /*+
      BEGIN_OUTLINE_DATA
      FULL(@"SEL$1" "DUAL"@"SEL$1")
      OUTLINE_LEAF(@"SEL$1")
      ALL_ROWS
      DB_VERSION('12.1.0.2')
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
* from dual;

这应该管用,但有点难看。理想情况下,您希望找到Oracle做出错误决策的根本原因—调查估计基数与实际基数、统计数据等。但是有很多方法可以做到这一点,而且需要很长时间。作为一种折衷办法,您可能希望使用这些提示,并尝试将其缩小到解决性能问题所需的一两个提示。

嗨,Jon,非常感谢您的回答。我已经尝试过你的执行计划显示方式-它显示与我的执行计划相同的信息。您能否提供一些建议,说明如何找到问题的根本原因,或者建议使用哪些提示(我尝试使用了,但被忽略了)?您是否将这两条语句作为常规SQL运行?不要通过某个IDE的解释计划“工具”运行它们。也许可以尝试以下提示:
select/*+index(p)*/p.unititemcode parentcode….
。如果没有完整的表和索引定义,很难重现计划。提示/*+index(p)*/不起作用。我不能在这里发布完整的表和索引定义,因为这些表非常大(超过100列),并且包含10-30个索引。错误计划的原因显然是返回行的数量增加了,但这些数量远小于表的行数。我开始认为这种行为是某种oracle的“内部连接方式”行为,因为递归返回的结果(计划中的“连接方式”是通过哈希连接连接的)。我没有发现影响这种行为的提示,有没有可能影响分层查询的提示?我只是尝试使用大纲数据提示,但没有成功。问题2的计划没有改变。嗨,乔恩,非常感谢你的回答。我已经尝试过你的执行计划显示方式-它显示与我的执行计划相同的信息。您能否提供一些建议,说明如何找到问题的根本原因,或者建议使用哪些提示(我尝试使用了,但被忽略了)?您是否将这两条语句作为常规SQL运行?不要通过某个IDE的解释计划“工具”运行它们。也许可以尝试以下提示:
select/*+index(p)*/p.unititemcode parentcode….
。如果没有完整的表和索引定义,很难重现计划。提示/*+index(p)*/不起作用。我不能在这里发布完整的表和索引定义,因为这些表非常大(超过100列),并且包含10-30个索引。错误计划的原因显然是返回行的数量增加了,但这些数量远小于表的行数。我开始认为这种行为是某种oracle的“内部连接方式”行为,因为递归返回的结果(计划中的“连接方式”是通过哈希连接连接的)。我没有发现影响这种行为的提示,有没有可能影响分层查询的提示?我只是尝试使用大纲数据提示,但没有成功。查询2的计划未更改。查询2正在处理更多数据。是什么让您认为查询1的计划是查询2增加的数据的正确计划?查询2返回的行数大约是查询1的2倍。查询1计划是正确的,因为进行索引完全扫描的表WI_UITEMPART包含数百万个这样的索引。查询1只生成约10000行,这意味着查询2生成约20000行。两个查询中的第一个选择都有一列
null unititemtype
,后面是
,其中m.unititemtype'SKID'
。因为
NULL
从不等于或不等于
NULL
,所以第一个查询中的任何行都不会包含在最终结果中,除非以connect by开头会返回被
where
子句消除的内容。另外,您是否尝试过对查询进行参数化,使其成为
sysdate-:bind\u变量
?用10运行一次,然后20,20应该重用计划。一个实验,而不是一个解决方案。关于NULL:你是对的,但它不会影响执行速度。正如您所说,我已经尝试使用bind变量-计划与查询2(坏计划)相同。查询2正在处理更多数据。你怎么会认为问题1是
explain plan for select * from dual; --Add your real query here.
select * from table(dbms_xplan.display(format => '+outline'));

Plan hash value: 272002086

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     1 |     2 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS FULL| DUAL |     1 |     2 |     2   (0)| 00:00:01 |
--------------------------------------------------------------------------

Outline Data
-------------

  /*+
      BEGIN_OUTLINE_DATA
      FULL(@"SEL$1" "DUAL"@"SEL$1")
      OUTLINE_LEAF(@"SEL$1")
      ALL_ROWS
      DB_VERSION('12.1.0.2')
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
select 
  /*+
      BEGIN_OUTLINE_DATA
      FULL(@"SEL$1" "DUAL"@"SEL$1")
      OUTLINE_LEAF(@"SEL$1")
      ALL_ROWS
      DB_VERSION('12.1.0.2')
      OPTIMIZER_FEATURES_ENABLE('12.1.0.2')
      IGNORE_OPTIM_EMBEDDED_HINTS
      END_OUTLINE_DATA
  */
* from dual;