【问题标题】:oracle execution plan, trying to understandoracle执行计划,试图理解
【发布时间】:2017-03-05 06:45:27
【问题描述】:
EXPLAIN PLAN FOR
  SELECT sightings.sighting_id, spotters.spotter_name,
         sightings.sighting_date
    FROM sightings
         INNER JOIN spotters
                 ON sightings.spotter_id = spotters.spotter_id
   WHERE sightings.spotter_id = 1255;

SELECT plan_table_output
  FROM table(dbms_xplan.display('plan_table',null,'basic'));




id   Operation                         Name
0    select statement        
1      nested loops
2        table access by index rowid   spotters
3          index unique scan           pk_spotter_ID
4        table access full             sightings

我试图了解这里到底发生了什么,这听起来对吗:

  1. 首先对 select 语句求值,输出中忽略 select 列表中的属性

  2. 然后嵌套循环计算 spotters.spotters_id =Sightings.spotter_id 上的内连接

  3. 按索引 rowid 的表访问从 spotters 表中检索具有第 3 步返回的 rowid 的行

  4. 索引唯一扫描,扫描 PK_SPOTTER_ID 索引中的 spotter_id 并在 spotters 表中查找 rowids 关联的行

  5. 表访问已满,然后完全扫描目击,直到找到Sighting_id = 1255

【问题讨论】:

  • 看来你放错了执行计划
  • 是的,对不起!我现在编辑了它
  • 从下往上从左到右读取执行计划。 Id 列不表示先执行操作。尽管执行计划以列表(表格)形式呈现给您,但它实际上是树形形式。所以你从树叶开始读它。 1. Index unique scan 先到后 2. sightings table access full 3. spotters 被索引 rowid 访问 4. nested loop 最后是 5. select find out more

标签: sql oracle execution


【解决方案1】:

注意:此答案是指问题的原始版本。

Oracle 正在完整读取这两个表。

它基于join 键对每个表进行哈希处理——“重新排序”表,使相似的键出现在彼此附近。

它正在加入。

然后它会为最终的select 进行计算并将结果返回给用户。

【讨论】:

  • 只有一张表被提前散列。正在流式传输另一个表。
  • @NicholasKrasnov,这个问题最初是用包含哈希连接的错误执行计划发布的。
  • @DuduMarkovitz 啊,我明白了,Op 在发布答案后编辑了这个问题......尽管对哈希连接处理的描述不正确,我还是会删除我之前的评论。
  • @NicholasKrasnov,你可以看到我已经评论了哈希连接处理。
【解决方案2】:

步骤似乎基本正确,但应该自下而上。 投影(选择相关列)最好在扫描阶段尽早完成。 索引操作是 SEEK(你不是在扫描整个索引)

【讨论】:

  • @01ldaniels,它回答了你的问题吗?您需要澄清一下吗?
【解决方案3】:

这就是非正式地以正确的顺序发生的事情:

-- The index pk_spotter_id is scanned for at most one row that satisfies spotter_id = 1255
3          index unique scan           pk_spotter_ID

-- The spotter_name column is fetched from the table spotters for the previously found row
2        table access by index rowid   spotters

-- A nested loop is run for each (i.e. at most one) of the previously found rows
1      nested loops

-- That nested loop will scan the entire sightings table for rows that match the join
-- predicate sightings.spotter_id = spotters.spotter_id
4        table access full             sightings

-- That'll be it for your select statement
0    select statement        

一般情况下(有很多例外),Oracle 执行计划是可以读取的

  • 自下而上
  • 第一个兄弟优先

这意味着你沿着树向下直到找到第一个叶子操作(例如#3),它将“首先”执行,其结果被提供给父节点(例如#2),所有兄弟节点都是然后自上而下执行,所有兄弟姐妹的结果也被馈送到父级,然后父级结果被馈送到祖父级(例如#1),直到您到达顶部操作。

这是对所发生情况的非常非正式的解释。请注意,一旦语句变得更复杂,这些规则将有许多例外情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-12-09
    • 2017-03-11
    • 2012-03-07
    • 2012-09-02
    • 1970-01-01
    • 2013-09-08
    • 2021-06-16
    • 2013-10-02
    相关资源
    最近更新 更多