From a92617b82d922d5ebac7342bd8c212e0eb5b4553 Mon Sep 17 00:00:00 2001 From: "Andrey V. Lepikhov" Date: Mon, 9 Dec 2019 18:25:04 +0500 Subject: [PATCH] Skip scan of outer subtree if inner of the NestedLoop node is guaranteed empty. --- src/backend/executor/nodeNestloop.c | 8 ++++++++ src/include/nodes/execnodes.h | 1 + src/test/regress/expected/partition_prune.out | 8 ++++---- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/backend/executor/nodeNestloop.c b/src/backend/executor/nodeNestloop.c index fc6667ef82..4a7da5406d 100644 --- a/src/backend/executor/nodeNestloop.c +++ b/src/backend/executor/nodeNestloop.c @@ -164,6 +164,11 @@ ExecNestLoop(PlanState *pstate) { ENL1_printf("no inner tuple, need new outer tuple"); + if (node->nl_InnerEmpty && list_length(nl->nestParams) == 0 && + (node->js.jointype == JOIN_INNER || + node->js.jointype == JOIN_SEMI)) + return NULL; + node->nl_NeedNewOuter = true; if (!node->nl_MatchedOuter && @@ -200,6 +205,8 @@ ExecNestLoop(PlanState *pstate) */ continue; } + else + node->nl_InnerEmpty = false; /* * at this point we have a new pair of inner and outer tuples so we @@ -327,6 +334,7 @@ ExecInitNestLoop(NestLoop *node, EState *estate, int eflags) { case JOIN_INNER: case JOIN_SEMI: + nlstate->nl_InnerEmpty = true; break; case JOIN_LEFT: case JOIN_ANTI: diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h index 692438d6df..8829433347 100644 --- a/src/include/nodes/execnodes.h +++ b/src/include/nodes/execnodes.h @@ -1847,6 +1847,7 @@ typedef struct NestLoopState JoinState js; /* its first field is NodeTag */ bool nl_NeedNewOuter; bool nl_MatchedOuter; + bool nl_InnerEmpty; TupleTableSlot *nl_NullInnerTupleSlot; } NestLoopState; diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out index f9eeda60e6..04cfe0944e 100644 --- a/src/test/regress/expected/partition_prune.out +++ b/src/test/regress/expected/partition_prune.out @@ -2455,9 +2455,9 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a; Heap Blocks: exact=1 -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) - -> Bitmap Heap Scan on ab_a1_b3 ab_2 (actual rows=0 loops=1) + -> Bitmap Heap Scan on ab_a1_b3 ab_2 (never executed) Recheck Cond: (a = 1) - -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=0 loops=1) + -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) Index Cond: (a = 1) -> Materialize (actual rows=0 loops=1) -> Bitmap Heap Scan on ab_a1_b1 ab_a1_1 (actual rows=0 loops=1) @@ -2496,9 +2496,9 @@ update ab_a1 set b = 3 from ab where ab.a = 1 and ab.a = ab_a1.a; Heap Blocks: exact=1 -> Bitmap Index Scan on ab_a1_b2_a_idx (actual rows=1 loops=1) Index Cond: (a = 1) - -> Bitmap Heap Scan on ab_a1_b3 ab_2 (actual rows=0 loops=1) + -> Bitmap Heap Scan on ab_a1_b3 ab_2 (never executed) Recheck Cond: (a = 1) - -> Bitmap Index Scan on ab_a1_b3_a_idx (actual rows=1 loops=1) + -> Bitmap Index Scan on ab_a1_b3_a_idx (never executed) Index Cond: (a = 1) -> Materialize (actual rows=0 loops=1) -> Bitmap Heap Scan on ab_a1_b3 ab_a1_3 (actual rows=0 loops=1) -- 2.17.1