Oracle 11G - PK索引未在Join上使用,采用全扫描方式

时间:2012-07-19 18:16:01

标签: oracle oracle10g oracle11g oracle11gr2

我知道Oracle有时“判断”最好执行全表扫描而不是索引扫描,但是仍处于“学习阶段”,我只是想更好地理解“何时”oracle将确定最佳路线。例如,我有简单的查询:

Select *
  FROM GLMV_JOURNAL_LOGS JLOG 
       INNER JOIN GLMV_Transact_Details TDTL 
          ON TDTL.TR_REF_NO = JLOG.TR_REF_NO 
         AND TDTL.SCAT_KEY = JLOG.Scat_key 
         AND TDTL.CASE_KEY = JLOG.CASE_KEY 
         AND TDTL.TR_CD = JLOG.TR_CD 
       INNER JOIN FUND_DESC FDDC 
          ON FDDC.FD_DESC_ID = TDTL.FD_DESC_ID  
       INNER JOIN FD_RATES FDRT 
          ON  FDRT.FDRT_KEY = TDTL.FDRT_KEY
       INNER JOIN BEN_TYPES BNTP 
          ON BNTP.BNTP_KEY = FDRT.BNTP_KEY 
 WHERE JLOG.JRNL_CD  = '0' 
   AND JLOG.SRC_CD = '2' 
   AND JLOG.MKEY_FD_NUM <> 0 
   AND NVL(JLOG.TMOV_KEY, -1) > 0 
   AND NVL(JLOG.ORIG_SCAT_KEY, 1) = 1 
   AND TDTL.STAT_CD <> '4' 
   AND NVL(TDTL.ORIG_SCAT_KEY, 1) = 1 

FD_RATES上的连接正在加入PK值,我还在GLMV_Transact_Details上创建了一个相应的索引,认为可以防止全表扫描,但是,根据下面的解释计划,它不是,即使在我之后也是如此执行索引重建和收集表统计信息,结果仍然相同:

Explain Plan

现在,如果我进入我的查询并添加以下where子句:

AND  FDRT.FDRT_KEY = 100

索引当然会开始,但我想我很好奇为什么它不是在进行内部连接时....任何提示?

3 个答案:

答案 0 :(得分:4)

优化器估计FD_RATES上的全表扫描的成本为106.此反馈的连接具有416的估计基数,以及为该连接提供的其他行源。如果我们用嵌套循环替换散列连接,对每一行进行唯一索引(PK)查找,则循环的每次迭代的成本至少为1,可能为2或3,我们认为会有是416次迭代,因此成本至少为416,可能是两倍或三倍,这远远超过了进行全表扫描的估计成本。

现在,估计可能是错误的。根据我的经验,要看的主要是计划中显示的基数。如果这些相当准确,那么Oracle很有可能选择合理有效的连接顺序和访问路径 - 不一定是最有效但最接近的。

如果您想尝试强制进行索引扫描以查看其执行情况,我相信您想要的提示是:

Select /*+ INDEX(fdrt) */ *
...

答案 1 :(得分:2)

我将忽略您的示例,并尝试回答您的FTS与索引问题:)

通常,使用索引的原因是最小化您需要读取的数据块以满足您的查询。这在很大程度上取决于数据在表格中的物理存储方式。您选择的行的百分比没有区别,而是使用索引而不是全表扫描可以避免的块数。例如,如果您有一个包含3000个块的3000万行的表,并且您想要选择15,000行(或.5%),那么您应该使用索引吗?好吧,如果所有15,000行都在最后200个块中,那么索引肯定是有道理的。但是,如果查询必须从每个数据块中获取5行以获得15,000行,则完整的表扫描更有意义,因为您必须触摸所有块。

Cary Millsap使用了一个很好的思考Oracle索引的例子,比如书中的索引。如果您有一本关于oracle的书,并且您查找“分区”,它可能会指向您在相对较小的页面集中发生的很多事情。所以在这种情况下,使用索引是一个好主意。但是,如果您查找“行”,它可能与“分区”具有相同的出现次数,但它们将分布在大多数页面上。在这种情况下,最好“全扫描”并按顺序读取每个页面,而不是在页面和索引之间来回翻转。

Oracle在索引中存储关于表中数据的物理存储方式的近似值,并在确定选择哪个路径时使用该信息。显然,优化器中的内容比这更多(并且您可以使用错误的统计信息或参数设置来破坏它),但这应该可以帮助您入门。

答案 2 :(得分:0)

我没有足够的信息来提供完整的答案,但这里有一些评论:

  • 我不会像你这样简单地称为5表连接。你可以放一张桌子吗?
  • 如果表格很大,全表扫描只会很糟糕。对于较小的表,与基于索引的访问没有区别。
  • 您可以使用提示(嵌入到注释中)来指示优化程序使用某个访问路径。