【读书笔记】【收获,不止Oracle】嵌套循环表(Nested Loops Join)

本次试验用于探究嵌套循环表的访问次数。

1.构造t1和t2表,用于嵌套查询。

SYS@ orcl>DROP TABLE t1 CASCADE CONSTRAINTS PURGE;

Table dropped.

SYS@ orcl>DROP TABLE t2 CASCADE CONSTRAINTS PURGE;

Table dropped.

SYS@ orcl>CREATE TABLE t1(
  2  id number not null,
  3  n number,
  4  contents varchar2(4000)
  5  )
  6  ;

Table created.

SYS@ orcl>CREATE TABLE t2(
  2  id number not null,
  3  t1_id number not null,
  4  n number,
  5  contents varchar2(4000)
  6  )
  7  ;

Table created.

2.t1表投入100条数据,t2表投入100000条数据。、

SYS@ orcl>execute dbms_random.seed(0);

PL/SQL procedure successfully completed.

SYS@ orcl>INSERT INTO t1
  2  SELECT 
  3  rownum,rownum,dbms_random.string('a',50)
  4  FROM dual 
  5  CONNECT BY level<=100
  6  ORDER BY dbms_random.random;

100 rows created.

SYS@ orcl>INSERT INTO t2
  2  SELECT rownum,rownum,rownum,dbms_random.string('b',50)
  3  FROM dual
  4  CONNECT BY level<=100000
  5  ORDER BY dbms_random.random; 

100000 rows created.


SYS@ orcl>commit;

Commit complete.


SYS@ orcl>select count(*) from t1;

  COUNT(*)
----------
       100

SYS@ orcl>select count(*) from t2;

  COUNT(*)
----------
    100000

3.只是【t1.id=t2.t1_id】的情况下,执行如下语句。

SELECT /*+leading(t1) use_nl(t2)*/*
FROM t1,t2
WHERE t1.id=t2.t1_id;

观察执行计划

SYS@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  6cy5taz2tutgz, child number 0
-------------------------------------
SELECT /*+leading(t1) use_nl(t2)*/* FROM t1,t2 WHERE t1.id=t2.t1_id

Plan hash value: 1967407726

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   1 |  NESTED LOOPS      |      |      1 |    100 |    100 |00:00:00.83 |   98517 |
|   2 |   TABLE ACCESS FULL| T1   |      1 |    100 |    100 |00:00:00.01 |      10 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|*  3 |   TABLE ACCESS FULL| T2   |    100 |      1 |    100 |00:00:00.83 |   98507 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("T1"."ID"="T2"."T1_ID")

Note
-----
   - dynamic sampling used for this statement

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


23 rows selected.

4.多了【t1.n in(17,19)】条件

SELECT /*+leading(t1) use_nl(t2)*/*
FROM t1,t2
WHERE t1.id=t2.t1_id
AND t1.n in(17,19);

观察执行计划

SYS@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  bh8yn920472bt, child number 0
-------------------------------------
SELECT /*+leading(t1) use_nl(t2)*/* FROM t1,t2 WHERE t1.id=t2.t1_id AND t1.n
in(17,19)

Plan hash value: 1967407726

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   1 |  NESTED LOOPS      |      |      1 |      2 |      2 |00:00:00.01 |    1975 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|*  2 |   TABLE ACCESS FULL| T1   |      1 |      2 |      2 |00:00:00.01 |       4 |
|*  3 |   TABLE ACCESS FULL| T2   |      2 |      1 |      2 |00:00:00.01 |    1971 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter(("T1"."N"=17 OR "T1"."N"=19))
   3 - filter("T1"."ID"="T2"."T1_ID")

Note

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----
   - dynamic sampling used for this statement


25 rows selected.

5.改变检索条件【t1.n = 19】

SELECT /*+leading(t1) use_nl(t2)*/*
FROM t1,t2
WHERE t1.id=t2.t1_id
AND t1.n = 19;

观察执行计划

SYS@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  7pzkjc7sd65a6, child number 0
-------------------------------------
SELECT /*+leading(t1) use_nl(t2)*/* FROM t1,t2 WHERE t1.id=t2.t1_id AND t1.n
= 19

Plan hash value: 1967407726

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   1 |  NESTED LOOPS      |      |      1 |      1 |      1 |00:00:00.01 |     990 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|*  2 |   TABLE ACCESS FULL| T1   |      1 |      1 |      1 |00:00:00.01 |       4 |
|*  3 |   TABLE ACCESS FULL| T2   |      1 |      1 |      1 |00:00:00.01 |     986 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("T1"."N"=19)
   3 - filter("T1"."ID"="T2"."T1_ID")

Note

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----
   - dynamic sampling used for this statement


25 rows selected.

6.改变检索条件【AND t1.n = 9999999999】

SYS@ orcl>select * from table(dbms_xplan.display_cursor(null,null,'allstats last'));

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
SQL_ID  5kpy1wbydnghk, child number 0
-------------------------------------
SELECT /*+leading(t1) use_nl(t2)*/* FROM t1,t2 WHERE t1.id=t2.t1_id AND t1.n
= 9999999999

Plan hash value: 1967407726

-------------------------------------------------------------------------------------
| Id  | Operation          | Name | Starts | E-Rows | A-Rows |   A-Time   | Buffers |
-------------------------------------------------------------------------------------
|   1 |  NESTED LOOPS      |      |      1 |      1 |      0 |00:00:00.01 |       3 |

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|*  2 |   TABLE ACCESS FULL| T1   |      1 |      1 |      0 |00:00:00.01 |       3 |
|*  3 |   TABLE ACCESS FULL| T2   |      0 |      1 |      0 |00:00:00.01 |       0 |
-------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("T1"."N"=9999999999)
   3 - filter("T1"."ID"="T2"."T1_ID")

Note

PLAN_TABLE_OUTPUT
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----
   - dynamic sampling used for this statement


25 rows selected.

总结:

循环嵌套表中驱动表(t1)返回多少条记录,被驱动表就访问多少次。




Oracle中的Nested Loop Join嵌套循环连接)是一种常用的连接方式,它的原理是将外层查询结果作为内层查询的参数进行查询,逐条进行匹配,直到找到匹配项为止。这种方式适用于其中一个的数据较小,另一个的数据较大的情况。 下面是一个简单的案例,假设有两张:订单(orders)和客户(customers),它们的结构如下: ``` ORDERS: ORDER_ID ORDER_DATE CUST_ID AMOUNT 1 2020-01-01 1 100 2 2020-01-02 2 200 3 2020-01-03 1 300 4 2020-01-04 3 400 CUSTOMERS: CUST_ID NAME AGE 1 Tom 20 2 Jerry 22 3 Lucy 25 ``` 现在需要将这两张根据CUST_ID字段进行连接,查询订单的客户姓名和年龄,可以使用以下SQL语句: ``` SELECT O.ORDER_ID, C.NAME, C.AGE FROM ORDERS O, CUSTOMERS C WHERE O.CUST_ID = C.CUST_ID; ``` 这里使用了传统的Join方式,如果数据量很大,连接速度就会很慢。现在我们可以使用Nested Loop Join来改进这个查询,以下是改进后的SQL语句: ``` SELECT O.ORDER_ID, C.NAME, C.AGE FROM ORDERS O, CUSTOMERS C WHERE O.CUST_ID = C.CUST_ID; ``` 这里使用了Nested Loop Join方式,可以提高连接速度。在这个查询中,ORDERS是外层查询,CUSTOMERS是内层查询。Oracle会从ORDERS中取出每一条记录,然后将其CUST_ID字段作为参数查询CUSTOMERS,逐条进行匹配,直到找到匹配项为止,然后将匹配结果与ORDERS的对应记录进行连接。这个过程会不断重复,直到查询完成。 需要注意的是,Nested Loop Join的效率受到内存大小和索引的影响,如果内存不足或者没有适当的索引,则需要进行大量的磁盘I/O操作,这就会降低连接速度。因此,在使用Nested Loop Join时,需要根据实际情况进行调整,以提高连接速度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值