@@ -256,28 +256,38 @@ public long estimateSizeRecursive(TaskAttemptContext ctx, String [] tableIds) th
256256 return size ;
257257 }
258258
259- @ VisibleForTesting
260- public boolean checkIfInMemoryInnerJoinIsPossible (TaskAttemptContext context , LogicalNode node , boolean left )
259+ public boolean isInnerJoinHashApplicable (TaskAttemptContext context , LogicalNode node , INPUT input )
261260 throws IOException {
262- String [] lineage = PlannerUtil .getRelationLineage (node );
263- long volume = estimateSizeRecursive (context , lineage );
264- boolean inMemoryInnerJoinFlag = false ;
261+ return isHashApplicable (context , node , SessionVars .INNER_HASH_JOIN_SIZE_LIMIT , input );
262+ }
265263
266- QueryContext queryContext = context .getQueryContext ();
264+ public boolean isOuterJoinHashApplicable (TaskAttemptContext context , LogicalNode node , INPUT input )
265+ throws IOException {
266+ return isHashApplicable (context , node , SessionVars .OUTER_HASH_JOIN_SIZE_LIMIT , input );
267+ }
267268
268- if (queryContext .containsKey (SessionVars .INNER_HASH_JOIN_SIZE_LIMIT )) {
269- inMemoryInnerJoinFlag = volume <= context .getQueryContext ().getLong (SessionVars .INNER_HASH_JOIN_SIZE_LIMIT );
270- } else {
271- inMemoryInnerJoinFlag = volume <= context .getQueryContext ().getLong (SessionVars .HASH_JOIN_SIZE_LIMIT );
272- }
269+ public boolean isCrossJoinHashApplicable (TaskAttemptContext context , LogicalNode node , INPUT input )
270+ throws IOException {
271+ return isHashApplicable (context , node , SessionVars .CROSS_HASH_JOIN_SIZE_LIMIT , input );
272+ }
273+
274+ private boolean isHashApplicable (TaskAttemptContext context , LogicalNode node ,
275+ SessionVars sessionVar , INPUT input ) throws IOException {
276+ String [] lineage = PlannerUtil .getRelationLineage (node );
277+ long volume = estimateSizeRecursive (context , lineage );
273278
274- LOG .info (String .format ("[%s] the volume of %s relations (%s) is %s and is %sfit to main maemory." ,
279+ boolean applicable = volume <= getThreshold (context .getQueryContext (), sessionVar );
280+ LOG .info (String .format ("[%s] the volume of %s relations (%s) is %s and is %sfit to main memory." ,
275281 context .getTaskId ().toString (),
276- ( left ? "Left" : "Right" ),
282+ input . name (). toLowerCase ( ),
277283 TUtil .arrayToString (lineage ),
278284 FileUtil .humanReadableByteCount (volume , false ),
279- (inMemoryInnerJoinFlag ? "" : "not " )));
280- return inMemoryInnerJoinFlag ;
285+ (applicable ? "" : "not " )));
286+ return applicable ;
287+ }
288+
289+ private long getThreshold (QueryContext context , SessionVars sessionVar ) {
290+ return context .getLong (sessionVar , context .getLong (SessionVars .HASH_JOIN_SIZE_LIMIT ));
281291 }
282292
283293 public PhysicalExec createJoinPlan (TaskAttemptContext context , JoinNode joinNode , PhysicalExec leftExec ,
@@ -325,6 +335,9 @@ private PhysicalExec createCrossJoinPlan(TaskAttemptContext context, JoinNode pl
325335 JoinAlgorithm algorithm = property .getJoin ().getAlgorithm ();
326336
327337 switch (algorithm ) {
338+ case IN_MEMORY_HASH_JOIN :
339+ LOG .info ("Join (" + plan .getPID () +") chooses [Hash Join]" );
340+ return new HashCrossJoinExec (context , plan , leftExec , rightExec );
328341 case NESTED_LOOP_JOIN :
329342 LOG .info ("Join (" + plan .getPID () +") chooses [Nested Loop Join]" );
330343 return new NLJoinExec (context , plan , leftExec , rightExec );
@@ -336,10 +349,19 @@ private PhysicalExec createCrossJoinPlan(TaskAttemptContext context, JoinNode pl
336349 LOG .error ("Invalid Cross Join Algorithm Enforcer: " + algorithm .name ());
337350 return new BNLJoinExec (context , plan , leftExec , rightExec );
338351 }
352+ }
339353
340- } else {
341- return new BNLJoinExec (context , plan , leftExec , rightExec );
354+ boolean inMemoryHashJoin =
355+ isCrossJoinHashApplicable (context , plan .getLeftChild (), INPUT .LEFT ) ||
356+ isCrossJoinHashApplicable (context , plan .getRightChild (), INPUT .RIGHT );
357+
358+ if (inMemoryHashJoin ) {
359+ LOG .info ("Join (" + plan .getPID () +") chooses [Hash Join]" );
360+ // returns two PhysicalExec. smaller one is 0, and larger one is 1.
361+ PhysicalExec [] orderedChilds = switchJoinSidesIfNecessary (context , plan , leftExec , rightExec );
362+ return new HashCrossJoinExec (context , plan , orderedChilds [1 ], orderedChilds [0 ]);
342363 }
364+ return new BNLJoinExec (context , plan , leftExec , rightExec );
343365 }
344366
345367 private PhysicalExec createInnerJoinPlan (TaskAttemptContext context , JoinNode plan ,
@@ -417,11 +439,9 @@ private PhysicalExec createInnerJoinPlan(TaskAttemptContext context, JoinNode pl
417439
418440 private PhysicalExec createBestInnerJoinPlan (TaskAttemptContext context , JoinNode plan ,
419441 PhysicalExec leftExec , PhysicalExec rightExec ) throws IOException {
420- boolean inMemoryHashJoin = false ;
421- if (checkIfInMemoryInnerJoinIsPossible (context , plan .getLeftChild (), true )
422- || checkIfInMemoryInnerJoinIsPossible (context , plan .getRightChild (), false )) {
423- inMemoryHashJoin = true ;
424- }
442+ boolean inMemoryHashJoin =
443+ isInnerJoinHashApplicable (context , plan .getLeftChild (), INPUT .LEFT ) ||
444+ isInnerJoinHashApplicable (context , plan .getRightChild (), INPUT .RIGHT );
425445
426446 if (inMemoryHashJoin ) {
427447 LOG .info ("Join (" + plan .getPID () +") chooses [In-memory Hash Join]" );
@@ -480,19 +500,7 @@ private PhysicalExec createLeftOuterJoinPlan(TaskAttemptContext context, JoinNod
480500
481501 private PhysicalExec createBestLeftOuterJoinPlan (TaskAttemptContext context , JoinNode plan ,
482502 PhysicalExec leftExec , PhysicalExec rightExec ) throws IOException {
483- String [] rightLineage = PlannerUtil .getRelationLineage (plan .getRightChild ());
484- long rightTableVolume = estimateSizeRecursive (context , rightLineage );
485- boolean hashJoin ;
486-
487- QueryContext queryContext = context .getQueryContext ();
488-
489- if (queryContext .containsKey (SessionVars .OUTER_HASH_JOIN_SIZE_LIMIT )) {
490- hashJoin = rightTableVolume < queryContext .getLong (SessionVars .OUTER_HASH_JOIN_SIZE_LIMIT );
491- } else {
492- hashJoin = rightTableVolume < queryContext .getLong (SessionVars .HASH_JOIN_SIZE_LIMIT );
493- }
494-
495- if (hashJoin ) {
503+ if (isOuterJoinHashApplicable (context , plan , INPUT .RIGHT )) {
496504 // we can implement left outer join using hash join, using the right operand as the build relation
497505 LOG .info ("Left Outer Join (" + plan .getPID () +") chooses [Hash Join]." );
498506 return new HashLeftOuterJoinExec (context , plan , leftExec , rightExec );
@@ -508,19 +516,7 @@ private PhysicalExec createBestRightJoinPlan(TaskAttemptContext context, JoinNod
508516 PhysicalExec leftExec , PhysicalExec rightExec ) throws IOException {
509517 //if the left operand is small enough => implement it as a left outer hash join with exchanged operators (note:
510518 // blocking, but merge join is blocking as well)
511- String [] outerLineage4 = PlannerUtil .getRelationLineage (plan .getLeftChild ());
512- long leftTableVolume = estimateSizeRecursive (context , outerLineage4 );
513- boolean hashJoin ;
514-
515- QueryContext queryContext = context .getQueryContext ();
516-
517- if (queryContext .containsKey (SessionVars .OUTER_HASH_JOIN_SIZE_LIMIT )) {
518- hashJoin = leftTableVolume < queryContext .getLong (SessionVars .OUTER_HASH_JOIN_SIZE_LIMIT );
519- } else {
520- hashJoin = leftTableVolume < queryContext .getLong (SessionVars .HASH_JOIN_SIZE_LIMIT );
521- }
522-
523- if (hashJoin ){
519+ if (isOuterJoinHashApplicable (context , plan , INPUT .LEFT )){
524520 LOG .info ("Right Outer Join (" + plan .getPID () +") chooses [Hash Join]." );
525521 return new HashLeftOuterJoinExec (context , plan , rightExec , leftExec );
526522 } else {
0 commit comments