zoukankan      html  css  js  c++  java
  • Oracle Hash Join被驱动表被访问0次的另外一种情况

    Oracle Hash Join被驱动表被访问0次的另外一种情况

    前言

    遇到了这样子的情况,HJ中驱动表满足条件的有大于0行的数据,但是被驱动表却一次都不访问,如下执行计划所示。

    -----------------------------------------------------------------------------------------------------------------
    | Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |      |      1 |        |      1 |00:00:00.01 |       3 |       |       |          |
    |   1 |  SORT AGGREGATE     |      |      1 |      1 |      1 |00:00:00.01 |       3 |       |       |          |
    |*  2 |   HASH JOIN         |      |      1 |      1 |      0 |00:00:00.01 |       3 |  1172K|  1172K|  441K (0)|
    |*  3 |    TABLE ACCESS FULL| BB   |      1 |      2 |      2 |00:00:00.01 |       3 |       |       |          |
    |*  4 |    TABLE ACCESS FULL| AA   |      0 |      2 |      0 |00:00:00.01 |       0 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("BB"."NAME"="AA"."NAME")
       3 - filter(("BB"."ID"=3 OR "BB"."ID"=5))
       4 - filter(("AA"."ID"=3 OR "AA"."ID"=5))

    id3的A-Rows表示有2行符合条件的数据,但是id4步骤却一次都不执行。

    HJ表访问次数各种情况

    1. 驱动表1次,被驱动表1次
    2. 驱动表1次,被驱动表0次
    3. 驱动表0次,被驱动表0次

    其中,第2种情况有两种原因导致,我们讨论就是其中一种。

    构造环境

    11.2.0.4.0。

    aa表和bb表是一样的。

    21:14:47 ZKM@test(934)> select * from aa;
    
            ID NAME
    ---------- ------------------------------------------------------------
             1 a
             2 b
             3
             4 d
             5
             6 a
    
    6 rows selected.
    
    Elapsed: 00:00:00.00
    21:23:18 ZKM@test(934)> select * from bb;
    
            ID NAME
    ---------- ------------------------------------------------------------
             1 a
             2 b
             3
             4 d
             5
             6 a
    
    6 rows selected.
    
    Elapsed: 00:00:00.00

    演示情况1

    驱动表访问1次,被驱动表访问1次。

    21:23:21 ZKM@test(934)> select count(*) from aa,bb where aa.name=bb.name;
    
      COUNT(*)
    ----------
             6
    
    Elapsed: 00:00:00.01
    21:25:16 ZKM@test(934)> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SQL_ID  2y1sdr2uydju8, child number 0
    -------------------------------------
    select count(*) from aa,bb where aa.name=bb.name
    
    Plan hash value: 532233124
    
    -----------------------------------------------------------------------------------------------------------------
    | Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |      |      1 |        |      1 |00:00:00.01 |       6 |       |       |          |
    |   1 |  SORT AGGREGATE     |      |      1 |      1 |      1 |00:00:00.01 |       6 |       |       |          |
    |*  2 |   HASH JOIN         |      |      1 |      5 |      6 |00:00:00.01 |       6 |  2616K|  2616K|  840K (0)|
    |   3 |    TABLE ACCESS FULL| AA   |      1 |      6 |      6 |00:00:00.01 |       3 |       |       |          |
    |   4 |    TABLE ACCESS FULL| BB   |      1 |      6 |      6 |00:00:00.01 |       3 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("AA"."NAME"="BB"."NAME")
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    25 rows selected.
    
    Elapsed: 00:00:00.06

    演示情况3

    驱动表访问0次,被驱动表访问0次。

    21:25:17 ZKM@qadb1(934)> select count(*) from aa,bb where aa.name=bb.name and 1=2;
    
      COUNT(*)
    ----------
             0
    
    Elapsed: 00:00:00.00
    21:26:40 ZKM@qadb1(934)> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SQL_ID  dy95brx8h9u5b, child number 0
    -------------------------------------
    select count(*) from aa,bb where aa.name=bb.name and 1=2
    
    Plan hash value: 2229986580
    
    --------------------------------------------------------------------------------------------------------
    | Id  | Operation            | Name | Starts | E-Rows | A-Rows |   A-Time   |  OMem |  1Mem | Used-Mem |
    --------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT     |      |      1 |        |      1 |00:00:00.01 |       |       |          |
    |   1 |  SORT AGGREGATE      |      |      1 |      1 |      1 |00:00:00.01 |       |       |          |
    |*  2 |   FILTER             |      |      1 |        |      0 |00:00:00.01 |       |       |          |
    |*  3 |    HASH JOIN         |      |      0 |      5 |      0 |00:00:00.01 |  1421K|  1421K|          |
    |   4 |     TABLE ACCESS FULL| AA   |      0 |      6 |      0 |00:00:00.01 |       |       |          |
    |   5 |     TABLE ACCESS FULL| BB   |      0 |      6 |      0 |00:00:00.01 |       |       |          |
    --------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - filter(NULL IS NOT NULL)
       3 - access("AA"."NAME"="BB"."NAME")
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    27 rows selected.
    
    Elapsed: 00:00:00.04

    演示情况2

    驱动表访问1次,被驱动表访问0次。

    其中的一种情况如下,驱动表访问过滤条件后不存在符合条件的数据,如下,id3的A-Rows为0,那么id4步骤就不会再执行了。

    21:28:08 ZKM@test(934)> select  count(*) from bb,aa where bb.name=aa.name and aa.id=99;
    
      COUNT(*)
    ----------
             0
    
    Elapsed: 00:00:00.01
    21:28:16 ZKM@test(934)> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SQL_ID  gdsu06n1bxz5k, child number 0
    -------------------------------------
    select  count(*) from bb,aa where bb.name=aa.name and aa.id=99
    
    Plan hash value: 532233124
    
    -----------------------------------------------------------------------------------------------------------------
    | Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |      |      1 |        |      1 |00:00:00.01 |       3 |       |       |          |
    |   1 |  SORT AGGREGATE     |      |      1 |      1 |      1 |00:00:00.01 |       3 |       |       |          |
    |*  2 |   HASH JOIN         |      |      1 |      1 |      0 |00:00:00.01 |       3 |  1172K|  1172K|  457K (0)|
    |*  3 |    TABLE ACCESS FULL| AA   |      1 |      1 |      0 |00:00:00.01 |       3 |       |       |          |
    |   4 |    TABLE ACCESS FULL| BB   |      0 |      6 |      0 |00:00:00.01 |       0 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("BB"."NAME"="AA"."NAME")
       3 - filter("AA"."ID"=99)
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    26 rows selected.
    
    Elapsed: 00:00:00.02

    另外一种情况,驱动表过滤后存在符合条件的数据,但是被驱动表仍旧是被访问0次。

    如下,id3处的A-Rows表示有2行符合条件数据,但是id4的starts为0,证明被驱动表aa被访问了0次。

    21:29:31 ZKM@test(934)> select  count(*) from bb,aa where bb.name=aa.name and bb.id in (3,5) and aa.id in (3,5);
    
      COUNT(*)
    ----------
             0
    
    Elapsed: 00:00:00.00
    21:32:15 ZKM@test(934)> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SQL_ID  36gd0c4fcp13h, child number 0
    -------------------------------------
    select  count(*) from bb,aa where bb.name=aa.name and bb.id in (3,5)
    and aa.id in (3,5)
    
    Plan hash value: 4233150
    
    -----------------------------------------------------------------------------------------------------------------
    | Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |      |      1 |        |      1 |00:00:00.01 |       3 |       |       |          |
    |   1 |  SORT AGGREGATE     |      |      1 |      1 |      1 |00:00:00.01 |       3 |       |       |          |
    |*  2 |   HASH JOIN         |      |      1 |      1 |      0 |00:00:00.01 |       3 |  1172K|  1172K|  441K (0)|
    |*  3 |    TABLE ACCESS FULL| BB   |      1 |      2 |      2 |00:00:00.01 |       3 |       |       |          |
    |*  4 |    TABLE ACCESS FULL| AA   |      0 |      2 |      0 |00:00:00.01 |       0 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("BB"."NAME"="AA"."NAME")
       3 - filter(("BB"."ID"=3 OR "BB"."ID"=5))
       4 - filter(("AA"."ID"=3 OR "AA"."ID"=5))
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    28 rows selected.
    
    Elapsed: 00:00:00.03

    为什么会出现这种情况,原因是id3处过滤bb表后的两行数据的连接条件的字段name均为空,因此直接hash join去计算的时候明显不会有aa表与之相符合的数据。

    21:40:29 ZKM@test(934)> select * from bb where bb.id in (3,5);
    
            ID NAME
    ---------- ------------------------------------------------------------
             3
             5
    
    Elapsed: 00:00:00.00

    若把条件改为bb.id in (1,3,5),其中,当bb.id=1时,bb.name不为空,那么即使只有一个不为空的连接条件字段值,被驱动表也会被访问1次。

    21:41:19 ZKM@test(934)> select /*+ leading(bb) use_hash(aa) */ count(*) from bb,aa where bb.name=aa.name and bb.id in (1,3,5) and aa.id in (3,5);
    
      COUNT(*)
    ----------
             0
    
    Elapsed: 00:00:00.00
    21:42:01 ZKM@test(934)> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));
    
    PLAN_TABLE_OUTPUT
    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    SQL_ID  2pa4m63zsya7g, child number 0
    -------------------------------------
    select /*+ leading(bb) use_hash(aa) */ count(*) from bb,aa where
    bb.name=aa.name and bb.id in (1,3,5) and aa.id in (3,5)
    
    Plan hash value: 4233150
    
    -----------------------------------------------------------------------------------------------------------------
    | Id  | Operation           | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |
    -----------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT    |      |      1 |        |      1 |00:00:00.01 |       6 |       |       |          |
    |   1 |  SORT AGGREGATE     |      |      1 |      1 |      1 |00:00:00.01 |       6 |       |       |          |
    |*  2 |   HASH JOIN         |      |      1 |      1 |      0 |00:00:00.01 |       6 |  2616K|  2616K|  680K (0)|
    |*  3 |    TABLE ACCESS FULL| BB   |      1 |      3 |      3 |00:00:00.01 |       3 |       |       |          |
    |*  4 |    TABLE ACCESS FULL| AA   |      1 |      2 |      2 |00:00:00.01 |       3 |       |       |          |
    -----------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - access("BB"."NAME"="AA"."NAME")
       3 - filter(("BB"."ID"=1 OR "BB"."ID"=3 OR "BB"."ID"=5))
       4 - filter(("AA"."ID"=3 OR "AA"."ID"=5))
    
    Note
    -----
       - dynamic sampling used for this statement (level=2)
    
    
    28 rows selected.
    
    Elapsed: 00:00:00.05
  • 相关阅读:
    cloudera cdh4 hue 安装
    设计模式Observer(观察者模式)
    编译android源码三(编译系统)
    centos 6.3 修改默认的系统语言
    Linux下查看文件和文件夹大小的df和du命令
    编译android源码二(下载源代码)
    devenv.exe
    Javascript和xml合用
    DataKeys的用法
    XSL(转)
  • 原文地址:https://www.cnblogs.com/PiscesCanon/p/14238213.html
Copyright © 2011-2022 走看看