繁体   English   中英

如何关联执行计划和SQL查询

[英]How to relate Execution Plan and SQL Query

这是查询

UPDATE hrs.rns_recon_ho c SET c.refr_numb = 
(
SELECT seqn_numb FROM hrs.rns_recon_ho p WHERE p.narr_1 = c.narr_1 
AND p.seqn_numb = p.refr_numb AND p.prod_code = 0
)
Where c.prod_code = 0 And c.refr_numb = 0 
AND c.narr_1 = '3/13/201211013198693442091'

这是它的执行计划

在此处输入图片说明 查询的哪一部分导致TABLE ACCESS(FULL)

编辑

我的错误,我应该更加清楚。 现在让我澄清自己,我需要知道如何将执行计划的一部分与查询的一部分联系起来。 例如

  1. 查询的哪一部分导致TABLE ACCESS(FULL)
  2. 查询的哪一部分导致TABLE ACCESS(BY GLOBAL INDEX ROWID)

但是,很明显INDEX(...)...PROD_CODE是由PROD_CODE字段引起的。

是否有任何经验法则,指南或技巧来识别? 或者,我们不知道,因为优化器不会告诉我们为什么选择了某个路径。

可能通过在一个表上提示来强制执行“全表扫描”,例如

UPDATE hrs.rns_recon_ho c SET c.refr_numb =
(
SELECT /*+ FULL(p) */ seqn_numb FROM hrs.rns_recon_ho p WHERE p.narr_1 = c.narr_1
AND p.seqn_numb = p.refr_numb AND p.prod_code = 0
)
Where c.prod_code = 0 And c.refr_numb = 0
AND c.narr_1 = '3/13/201211013198693442091'

要么

UPDATE /*+ FULL(c) */ hrs.rns_recon_ho c SET c.refr_numb =
(
SELECT seqn_numb FROM hrs.rns_recon_ho p WHERE p.narr_1 = c.narr_1
AND p.seqn_numb = p.refr_numb AND p.prod_code = 0
)
Where c.prod_code = 0 And c.refr_numb = 0
AND c.narr_1 = '3/13/201211013198693442091'

如果您的执行计划显示两个“全面扫描”,则您知道它最初是由另一个引起的。

让我重新创建:

CREATE TABLE RNS_RECON_HO ( PROD_CODE NUMBER,
            REFR_NUMB NUMBER,
            NARR_1 VARCHAR2 ( 25 ),
            SEQN_NUMB NUMBER primary key    );

CREATE INDEX TESTTT ON RNS_RECON_HO (PROD_CODE);
CREATE INDEX TESTTT1 ON RNS_RECON_HO (REFR_NUMB);
CREATE INDEX TESTTT2 ON RNS_RECON_HO (NARR_1);

现在重现您的计划:

SET AUTOTRACE ON

UPDATE
      RNS_RECON_HO C
SET
      C.REFR_NUMB    =
          ( SELECT
                 SEQN_NUMB
           FROM
                RNS_RECON_HO P
           WHERE
                    P.NARR_1 = C.NARR_1
                AND P.SEQN_NUMB = P.REFR_NUMB
                AND P.PROD_CODE = PROD_CODE )
WHERE
         C.PROD_CODE = 0
      AND C.REFR_NUMB = 0
      AND C.NARR_1 = '3/13/201211013198693442091';


0 rows updated.

Execution Plan
----------------------------------------------------------
   0       UPDATE STATEMENT Optimizer Mode=ALL_ROWS (Cost=2 Card=1 Bytes=78)
   1    0    UPDATE RNS_RECON_HO
   2    1      TABLE ACCESS FULL RNS_RECON_HO (Cost=2 Card=1 Bytes=78)
   3    1      TABLE ACCESS BY INDEX ROWID RNS_RECON_HO (Cost=5 Card=1 Bytes=91)
   4    3        INDEX RANGE SCAN TESTTT (Cost=1 Card=1)

Statistics
----------------------------------------------------------
        190  recursive calls
          0  spare statistic 3
          0  gcs messages sent
         25  db block gets from cache
          0  physical reads direct (lob)
          0  queue position update
          0  queue single row
          0  queue ocp pages
          0  HSC OLTP Compressed Blocks
          0  HSC IDL Compressed Blocks
          0  rows processed

原因

仅当索引比表扫描便宜(读取次数少)时,优化器才会选择使用索引。 这通常意味着WHERE子句条件需要映射到索引的前导(即最左侧)列。 因此,在where子句列上添加索引(PROD_CODE,REFR_NUMB,NARR_1)将避免这种情况。

确认检查一下

CREATE INDEX TESTTT3 ON RNS_RECON_HO (PROD_CODE, REFR_NUMB, NARR_1);

SET AUTOTRACE ON

UPDATE
      RNS_RECON_HO C
SET
      C.REFR_NUMB    =
          ( SELECT
                 SEQN_NUMB
           FROM
                RNS_RECON_HO P
           WHERE
                    P.NARR_1 = C.NARR_1
                AND P.SEQN_NUMB = P.REFR_NUMB
                AND P.PROD_CODE = PROD_CODE )
WHERE
         C.PROD_CODE = 0
      AND C.REFR_NUMB = 0
      AND C.NARR_1 = '3/13/201211013198693442091';

0 rows updated.

Execution Plan
----------------------------------------------------------
   0       UPDATE STATEMENT Optimizer Mode=ALL_ROWS (Cost=1 Card=1 Bytes=78)
   1    0    UPDATE RNS_RECON_HO
   2    1      INDEX RANGE SCAN TESTTT3 (Cost=1 Card=1 Bytes=78)
   3    1      TABLE ACCESS BY INDEX ROWID RNS_RECON_HO (Cost=27 Card=1 Bytes=91)
   4    3        INDEX FULL SCAN TESTTT3 (Cost=26 Card=1)

Statistics
----------------------------------------------------------
          1  recursive calls
          0  spare statistic 3
          0  gcs messages sent
          0  db block gets from cache
          0  physical reads direct (lob)
          0  queue position update
          0  queue single row
          0  queue ocp pages
          0  HSC OLTP Compressed Blocks
          0  HSC IDL Compressed Blocks
          0  rows processed

但这仅是改变计划,而绝不能保证您提供的输入有限,不会提高任何性能。

跟进:

外部查询正在进行FTS,因为它忽略了索引。 因此,当我们放置一个复合键时,索引对于优化器来说是直接的,并且使用相同的索引。 子查询正在使用索引,因为它与索引列上的外部查询联接在一起。

尽管您可以遵循核心规则接近可能的执行计划,但是如何确定准确的计划却无法100%实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM