Nested Loop

名称

嵌套循环连接算子

介绍

通过循环嵌套的方式获取关联数据,扫描时以外(左)表作为驱动表,先扫描驱动表,用读取的每一行驱动内表,当内(右)表的数据能够与之匹配时,进行关联

适合内表的关联列发生在唯一键值列或者主键列上的情况

举例

--清理环境
DROP TABLE t1 CASCADE;
DROP TABLE t2 CASCADE;

--创建环境
CREATE TABLE t1(id int, a int);
INSERT INTO t1 SELECT generate_series(1,10),random();
ANALYZE t1;

CREATE TABLE t2(id int,b int);
INSERT INTO t2 SELECT generate_series(1,10),random();
ANALYZE t2;

EXPLAIN ANALYZE SELECT * FROM t1 LEFT JOIN t2 ON TRUE WHERE t1.a!=t2.b;
                                               QUERY PLAN
--------------------------------------------------------------------------------------------------------
 Nested Loop(Inner Join)  (cost=7.11..16.46 rows=90 width=16) (actual time=0.07..0.11 rows=100 loops=1)
   Join Filter: ("outer".A <> "inner".B)
   ->  Seq Scan on T1  (cost=0.00..7.10 rows=10 width=8) (actual time=0.02..0.02 rows=10 loops=1)
   ->  Materialize  (cost=7.11..7.21 rows=10 width=8) (actual time=0.00..0.01 rows=10 loops=10)
         ->  Seq Scan on T2  (cost=0.00..7.10 rows=10 width=8) (actual time=0.01..0.02 rows=10 loops=1)
 Planning Time: 0.29 msec
 Execution Time: 0.20 msec
(7 rows)

EXPLAIN ANALYZE SELECT * FROM t1 LEFT JOIN t2 ON TRUE WHERE RANDOM()>1;
                                               QUERY PLAN
--------------------------------------------------------------------------------------------------------
 Nested Loop(Left Join)  (cost=7.11..16.71 rows=33 width=16) (actual time=0.04..0.10 rows=53 loops=1)
   Filter: (RANDOM() > 1::double precision)
   ->  Seq Scan on T1  (cost=0.00..7.10 rows=10 width=8) (actual time=0.01..0.02 rows=10 loops=1)
   ->  Materialize  (cost=7.11..7.21 rows=10 width=8) (actual time=0.00..0.00 rows=10 loops=10)
         ->  Seq Scan on T2  (cost=0.00..7.10 rows=10 width=8) (actual time=0.01..0.02 rows=10 loops=1)
 Planning Time: 0.50 msec
 Execution Time: 0.56 msec
(7 rows)

EXPLAIN ANALYZE SELECT * FROM t1 left JOIN t2 ON t2.id>100 WHERE a IN (SELECT b FROM t1) AND RANDOM()=1;
                                                 QUERY PLAN
------------------------------------------------------------------------------------------------------------
 Nested Loop(Left Semi Join)  (cost=7.13..21.56 rows=1 width=16) (actual time=0.05..0.05 rows=0 loops=1)
   Startup Filter: (RANDOM() = 1::double precision)
   ->  Nested Loop(Left Join)  (cost=7.13..14.45 rows=10 width=16) (actual time=0.05..0.05 rows=0 loops=1)
         Filter: ("outer".A = "inner".B)
         ->  Seq Scan on T1  (cost=0.00..7.10 rows=10 width=8) (actual time=0.02..0.03 rows=10 loops=1)
         ->  Materialize  (cost=7.13..7.14 rows=1 width=8) (actual time=0.00..0.00 rows=0 loops=10)
               ->  Seq Scan on T2  (cost=0.00..7.13 rows=1 width=8) (actual time=0.01..0.01 rows=0 loops=1)
                     Scan Key: (ID > 100)
   ->  RowcountMaterial  (cost=7.13..7.13 rows=10 width=0) (never executed)
         ->  Seq Scan on T1  (cost=0.00..7.10 rows=10 width=0) (never executed)
 Planning Time: 0.58 msec
 Execution Time: 0.19 msec
(12 rows)

EXPLAIN ANALYZE SELECT * FROM t1 left JOIN t2 ON t2.id>100 WHERE a NOT IN (SELECT b FROM t1) AND RANDOM()=1;
                                                               QUERY PLAN
----------------------------------------------------------------------------------------------------------------------------------------
 Nested Loop(Left Anti Semi Join)  (cost=7.13..21.54 rows=10 width=16) (actual time=0.05..0.07 rows=10 loops=1)
   Startup Anti Filter: ((("outer".A = "outer".B) OR ("outer".A IS NULL) OR ("outer".B IS NULL)) AND (RANDOM() = 1::double precision))
   ->  Nested Loop(Left Join)  (cost=7.13..14.43 rows=10 width=16) (actual time=0.04..0.05 rows=10 loops=1)
         ->  Seq Scan on T1  (cost=0.00..7.10 rows=10 width=8) (actual time=0.02..0.03 rows=10 loops=1)
         ->  Materialize  (cost=7.13..7.14 rows=1 width=8) (actual time=0.00..0.00 rows=0 loops=10)
               ->  Seq Scan on T2  (cost=0.00..7.13 rows=1 width=8) (actual time=0.02..0.02 rows=0 loops=1)
                     Scan Key: (ID > 100)
   ->  Seq Scan on T1  (cost=0.00..7.10 rows=10 width=0) (never executed)
 Planning Time: 0.60 msec
 Execution Time: 0.19 msec
(10 rows)
  • Inner Join 算子属性,表示 连接类型
  • Join Filter 限定条件,连接限定条件
  • Filter 限定条件,一些其他的限定
  • Startup Filter 限定条件,只对外表进行限定
  • Startup Anti Filter 限定条件, 只对外表进行限定