zoukankan      html  css  js  c++  java
  • 嵌套循环连接(nested loops join)原理

    嵌套循环连接(nested loops join)

       访问次数:驱动表返回几条,被驱动表访问多少次。

       驱动表是否有顺序:有。

       是否要排序:否。

       应用场景:  1.关联中有一个表比较小;

                                2.被关联表的关联字段上有索引;

                                3.索引的键值不应该重复率很高。

    如果你做过开发,就把它看成两层嵌套的for循环。

    下面我们来做个实验:

    SQL> create table test1 as select * from dba_objects where rownum <=100;

    SQL> create table test2 as select * from dba_objects where rownum <=1000;
    SQL> exec dbms_stats.gather_table_stats(user,'test1');

    SQL> exec dbms_stats.gather_table_stats(user,'test2');

    SQL> alter session set statistics_level=all;

    SQL> select /*+leading(t1) use_nl(t2)*/count(*)
      2    from test1 t1, test2 t2
      3   where t1.object_id = t2.object_id;

      COUNT(*)
    ----------
           100
    SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

    PLAN_TABLE_OUTPUT
    ---------------------------------------------------------------------------------------------------------
    SQL_ID  3v5gu7ppdsz67, child number 0
    -------------------------------------
    select /*+leading(t1) use_nl(t2)*/count(*)   from test1 t1, test2 t2  where
    t1.object_id = t2.object_id

    Plan hash value: 1459699139

    ----解释一下:

    Starts为该sql执行的次数。

    E-Rows为执行计划预计的行数。

    A-Rows为实际返回的行数。A-Rows跟E-Rows做比较,就可以确定哪一步执行计划出了问题。
    A-Time为每一步实际执行的时间(HH:MM:SS.FF),根据这一行可以知道该sql耗时在了哪个地方。
    Buffers为每一步实际执行的逻辑读或一致性读。
    Reads为物理读。
    OMem、1Mem为执行所需的内存评估值,0Mem为最优执行模式所需内存的评估值,1Mem为one-pass模式所需内存的评估值。
    0/1/M 为最优/one-pass/multipass执行的次数。
    Used-Mem耗的内存

    ---------------------------------------------------------------------------------------
    | Id  | Operation           | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    ---------------------------------------------------------------------------------------
    |   1 |  SORT AGGREGATE     |       |      1 |      1 |      1 |00:00:00.01 |    1504 |
    |   2 |   NESTED LOOPS      |       |      1 |    100 |    100 |00:00:00.01 |    1504 |
    |   3 |    TABLE ACCESS FULL| TEST1 |       1 |    100 |    100 |00:00:00.01 |       4 |
    |*  4 |    TABLE ACCESS FULL| TEST2 |     100 |      1 |    100 |00:00:00.01 |    1500 |

    ---------------------------------------------------------------------------------------

    Predicate Information (identified by operation id):
    ---------------------------------------------------
       4 - filter("T1"."OBJECT_ID"="T2"."OBJECT_ID")


    SQL> select /*+leading(t1) use_nl(t2)*/count(*)
      2    from test1 t1, test2 t2
      3   where t1.object_id = t2.object_id
      4     and t1.object_id in (10, 11, 12);

      COUNT(*)
    ----------
             3
    SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

    PLAN_TABLE_OUTPUT
    ---------------------------------------------------------------------------------------------------------
    SQL_ID  0skx6hyjtsncu, child number 0
    -------------------------------------
    select /*+leading(t1) use_nl(t2)*/count(*)   from test1 t1, test2 t2  where
    t1.object_id = t2.object_id    and t1.object_id in (10, 11, 12)
    ---------------------------------------------------------------------------------------
    | Id  | Operation           | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    ---------------------------------------------------------------------------------------
    |   1 |  SORT AGGREGATE     |       |      1 |      1 |      1 |00:00:00.01 |      49 |
    |   2 |   NESTED LOOPS      |       |      1 |      3 |      3 |00:00:00.01 |      49 |
    |*  3 |    TABLE ACCESS FULL| TEST1 |       1 |      3 |      3 |00:00:00.01 |       4 |
    |*  4 |    TABLE ACCESS FULL| TEST2 |       3 |      1 |      3 |00:00:00.01 |      45 |
    ---------------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       3 - filter(("T1"."OBJECT_ID"=10 OR "T1"."OBJECT_ID"=11 OR
                  "T1"."OBJECT_ID"=12))
       4 - filter((INTERNAL_FUNCTION("T2"."OBJECT_ID") AND
                  "T1"."OBJECT_ID"="T2"."OBJECT_ID"))

    SQL> select /*+leading(t1) use_nl(t2)*/count(*)
      2    from test1 t1, test2 t2
      3   where t1.object_id = t2.object_id
      4     and t1.object_id =10;

      COUNT(*)
    ----------
             1
    SQL> select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

    PLAN_TABLE_OUTPUT
    ---------------------------------------------------------------------------------------------------------
    SQL_ID  24g0zhvczyf2h, child number 0
    -------------------------------------
    select /*+leading(t1) use_nl(t2)*/count(*)   from test1 t1, test2 t2  where
    t1.object_id = t2.object_id    and t1.object_id =10
    Plan hash value: 1459699139
    ---------------------------------------------------------------------------------------
    | Id  | Operation           | Name  | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
    ---------------------------------------------------------------------------------------
    |   1 |  SORT AGGREGATE     |       |      1 |      1 |      1 |00:00:00.01 |      19 |
    |   2 |   NESTED LOOPS      |       |      1 |      1 |      1 |00:00:00.01 |      19 |
    |*  3 |    TABLE ACCESS FULL| TEST1 |       1 |      1 |      1 |00:00:00.01 |       4 |
    |*  4 |    TABLE ACCESS FULL| TEST2 |       1 |      1 |      1 |00:00:00.01 |      15 |
    ---------------------------------------------------------------------------------------
    Predicate Information (identified by operation id):
    ---------------------------------------------------
       3 - filter("T1"."OBJECT_ID"=10)
       4 - filter("T2"."OBJECT_ID"=10)

  • 相关阅读:
    北京最好的体检中心
    算法初级面试题04——递归/非递归遍历二叉树、直观打印二叉树、寻找后继前驱节点、序列化/反序列化、折纸问题、判断是否平衡/搜索/完全二叉树、求完全二叉的节点数
    算法初级面试题03——打印链表公共部分、判断链表是否为回文、按值划分链表为小于等于大于、复制随机指针链表、两链表相交判断的一系列问题
    算法初级面试题03——队列实现栈、栈实现队列、转圈打印矩阵、旋转矩阵、反转链表、之字打印矩阵、排序矩阵中找数
    算法初级面试题02——荷兰国旗问题、随机快速排序、堆排序、桶排序、相邻两数的最大差值问题、工程中的综合排序算法面试题
    算法初级面试题01——认识时间复杂度、对数器、 master公式计算时间复杂度、小和问题和逆序对问题
    JAVAEE——SpringBoot日志篇:日志框架SLF4j、日志配置、日志使用、切换日志框架
    JAVAEE——SpringBoot配置篇:配置文件、YAML语法、文件值注入、加载位置与顺序、自动配置原理
    JAVAEE——SpringBoot入门:简介、微服务、环境准备、helloworld与探究、快速构建项目
    JAVAEE——宜立方商城14:项目部署规划、Tomcat热部署、反向代理的配置
  • 原文地址:https://www.cnblogs.com/james1207/p/3400140.html
Copyright © 2011-2022 走看看