private boolean canShareBroadcastInputs(
      ParseContext pctx, MapJoinOperator mapJoinOp1, MapJoinOperator mapJoinOp2) throws SemanticException {
    if (mapJoinOp1.getNumParent() != mapJoinOp2.getNumParent()) {
      return false;
    }

    if (mapJoinOp1.getConf().getPosBigTable() != mapJoinOp2.getConf().getPosBigTable()) {
      return false;
    }

    // Map Joins when vectorized can have different formats for the hash tables built on the small table.
    // Reusing hash tables between different join type can lead to ClassCastException or even wrong results.
    if (ArrayUtils.isNotEmpty(mapJoinOp1.getConf().getConds())
        && ArrayUtils.isNotEmpty(mapJoinOp2.getConf().getConds())
        && mapJoinOp1.getConf().getConds()[0].getType() != mapJoinOp2.getConf().getConds()[0].getType()
        && (mapJoinOp1.getConf().isNoOuterJoin() || mapJoinOp2.getConf().isNoOuterJoin())) {
        return false;
    }


    for (int i = 0; i < mapJoinOp1.getNumParent(); i ++) {
      if (i == mapJoinOp1.getConf().getPosBigTable()) {
        continue;
      }

      ReduceSinkOperator parentRS1 = (ReduceSinkOperator) mapJoinOp1.getParentOperators().get(i);
      ReduceSinkOperator parentRS2 = (ReduceSinkOperator) mapJoinOp2.getParentOperators().get(i);

      if (!compareOperator(pctx, parentRS1, parentRS2)) {
        return false;
      }

      Operator<?> grandParent1 = parentRS1.getParentOperators().get(0);
      Operator<?> grandParent2 = parentRS2.getParentOperators().get(0);

      if (grandParent1 != grandParent2) {
        return false;
      }
    }

    return true;
  }
Try to reuse cache for broadcast side in mapjoin operators that share the same input.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/SharedWorkOptimizer.java