From b39e91501c101d67b92f3e6965da5dc111195f52 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Sun, 28 Jan 2007 23:21:26 +0000 Subject: Improve hash join to discard input tuples immediately if they can't match because they contain a null join key (and the join operator is known strict). Improves performance significantly when the inner relation contains a lot of nulls, as per bug #2930. --- src/backend/executor/nodeHashjoin.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'src/backend/executor/nodeHashjoin.c') diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 7f0801c69bd..b03086fb364 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.86 2007/01/05 22:19:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeHashjoin.c,v 1.87 2007/01/28 23:21:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -547,9 +547,8 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode, int curbatch = hashtable->curbatch; TupleTableSlot *slot; - if (curbatch == 0) - { /* if it is the first pass */ - + if (curbatch == 0) /* if it is the first pass */ + { /* * Check to see if first outer tuple was already fetched by * ExecHashJoin() and not used yet. @@ -559,7 +558,8 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode, hjstate->hj_FirstOuterTupleSlot = NULL; else slot = ExecProcNode(outerNode); - if (!TupIsNull(slot)) + + while (!TupIsNull(slot)) { /* * We have to compute the tuple's hash value. @@ -567,13 +567,22 @@ ExecHashJoinOuterGetTuple(PlanState *outerNode, ExprContext *econtext = hjstate->js.ps.ps_ExprContext; econtext->ecxt_outertuple = slot; - *hashvalue = ExecHashGetHashValue(hashtable, econtext, - hjstate->hj_OuterHashKeys); + if (ExecHashGetHashValue(hashtable, econtext, + hjstate->hj_OuterHashKeys, + (hjstate->js.jointype == JOIN_LEFT), + hashvalue)) + { + /* remember outer relation is not empty for possible rescan */ + hjstate->hj_OuterNotEmpty = true; - /* remember outer relation is not empty for possible rescan */ - hjstate->hj_OuterNotEmpty = true; + return slot; + } - return slot; + /* + * That tuple couldn't match because of a NULL, so discard it + * and continue with the next one. + */ + slot = ExecProcNode(outerNode); } /* -- cgit v1.2.3