【问题标题】:Reading Oracle Explain plan阅读 Oracle 解释计划
【发布时间】:2017-11-05 22:23:19
【问题描述】:
explain plan for 
    SELECT * FROM schema2.mv_a_data mv
      WHERE mv.routing_code_type_id    = 3
      AND mv.static_data_status_id    IN(5, 8)
      AND mv.acct_currency_ind_id NOT IN
         (SELECT DISTINCT te.acct_currency_ind_id 
          FROM schema1.tem_ele te 
          WHERE te.lis_tem_id IN      
                  (SELECT lis_tem_id 
                   FROM schema1.lis_tem 
                   WHERE lis_tem.template_type_id = 2
                   AND lis_tem.deleted_flag       = 'N'      )
      AND te.acct_currency_ind_id IS NOT NULL
    )
 ORDER BY mv.treasury_region_code, 
          mv.legal_entity_mnemonic, 
          mv.currency_code;

 select * 
 from TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE', null,'ADVANCED'));
------------------------------------------------------------------------------------
|  Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |           |   892 |   318K|    69   (2)| 00:00:01 |
|   1 |  SORT ORDER BY         |           |   892 |   318K|    69   (2)| 00:00:01 | 
|*  2 |   HASH JOIN RIGHT ANTI |           |   892 |   318K|    68   (0)| 00:00:01 | `
|   3 |    VIEW                | VW_NSO_1  |  1457 |  8742 |    11  (0) | 00:00:01 |
|*  4 |     HASH JOIN          |           |  1457 | 33511 |    11   (0)| 00:00:01 | 
|*  5 |      TABLE ACCESS FULL | lis_tem   |   100 |  1100 |     3   (0)| 00:00:01 | 
|*  6 |      TABLE ACCESS FULL | tem_ele   |  3271 | 39252 |     8   (0)| 00:00:01 | 
|*  7 |    MAT_VIEW ACCESS FULL| mv_a_data |  2348 |   825K|    57   (0)| 00:00:01 |

我正在尝试阅读给定的解释计划。在查看解释计划并根据 据我了解,首先 LIS_TEM 表和 TEM_ELE 的 FTS 完成,然后使用 HASH JOIN 将它们连接起来。

问题 1 - 我可以将此 HASH JOIN 更改为 NESTED LOOP 吗?

我只是为了学习目的而询问。我知道 HASH JOIN 在这里很好。 在 HASH JOIN 之后,我猜它会转到 ID3 即 VIEW VW_NSO_1 和 ID7 MAT_VIEW。

问题 2 - 这个 VIEW VW_NSO_1 是什么,SQL 查询的哪个子句负责将它带到这里?
问题 3 - 我将如何阅读计划的其余部分?
问题 4 - 为什么 HASH JOIN RIGHT ANTI 出现在图片中?

请协助我详细了解上述解释计划。谢谢,如果您需要更多详细信息,请告诉我。

【问题讨论】:

    标签: sql oracle performance oracle11g


    【解决方案1】:

    “我可以将此 HASH JOIN 更改为 NESTED LOOP 吗?”

    您可以尝试use_nl 提示。 Find out more

    “这个VIEW VW_NSO_1是什么,SQL查询的哪个子句负责把它带到这里来的?”

    VW_NSO_1 表示将IN 子查询取消嵌套到视图中。那是因为您的子查询使用 DISTINCT,所以保证了一个唯一的集合。此操作未记录在 11g 文档中,但 you can find it in the older Tuning Guides.

    “我将如何阅读计划的其余部分?”

    嗯,注意细节?基本上所有涉及的表都足够小并且缺乏有用的索引,因此优化器已经为全表扫描而努力。

    “为什么 HASH JOIN RIGHT ANTI 出现在图片中?”

    NOT IN 子查询视为一种外连接。您希望 MView 中的记录与子查询中的行不匹配 - 反连接。在您的查询中,这将是一个 LEFT OUTER JOIN。但是,优化器决定首先收集子查询的结果集比评估 MView 上的反连接(右外连接)更有效。 Dion Cho 在这方面写了一篇非常好的文章。 Find out more.

    【讨论】:

      【解决方案2】:

      视图 VW_NSO_1 是查询中的内联视图:

      (SELECT DISTINCT te.acct_currency_ind_id 
                FROM schema1.tem_ele te 
                WHERE te.lis_tem_id IN      
                        (SELECT lis_tem_id 
                         FROM schema1.lis_tem 
                         WHERE lis_tem.template_type_id = 2
                         AND lis_tem.deleted_flag       = 'N'      )
            AND te.acct_currency_ind_id IS NOT NULL
          )
      

      优化器已将您的“in”子句转换为哈希联接。 它还将您的“not in”子句转换为哈希连接右反。

      您所有的表都非常小,因此无需担心全扫描 - 优化器可能为您的数据选择了最佳策略。

      【讨论】:

      • 谢谢大家。非常有用的信息。正如我所说,我也在尝试阅读这样的解释计划,首先完成 LIS_TEM 的 ID5 FTS,然后完成 TEM_ELE 的 ID6 FTS。在此之后,这 2 个表使用 HASH JOIN 连接。在此之后“ID3 - VIEW - VW_NSO_1”和“ID7 - MAT_VIEW ACCESS FULL - MV_A_DATA”在同一行。因此优化器正在扫描 MAT_VIEW(前缀 mv.)的所有 WHERE 子句以及 VW_NSO_1 子句。那么 HASH JOIN RIGHT ANTI 是如何与 ID3 和 ID7 挂钩的呢?
      • 还是 HASH JOIN RIGHT ANTI 只与 ID3 VIEW 关联?如果这是正确的,那么是对 ID2 和 ID7 的结果进行 SORT ORDER BY 操作吗?或者我无法以这种方式阅读解释计划?你们能告诉我你会如何阅读这个解释计划吗?
      【解决方案3】:

      您可以使用查询提示来“强制”查询以使用特定的连接,尽管我不推荐这样做。如果它使用哈希,那么它可能是最好的选择。如果您认为使用不同的联接会更好,请确保您的统计信息是最新的

      Oracle 文档有助于查看每个操作在做什么: https://docs.oracle.com/cd/B10501_01/server.920/a96533/ex_plan.htm

      【讨论】:

      • 您或其他人可以回答问题2、3和4吗?
      猜你喜欢
      • 2020-09-01
      • 1970-01-01
      • 2012-11-12
      • 2012-12-16
      • 1970-01-01
      • 2013-02-02
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多