public boolean chooseBestSemiJoin(HiveLoptMultiJoin multiJoin) {
    // sort the join factors based on the cost of each factor filtered by
    // semijoins, if semijoins have been chosen
    int nJoinFactors = multiJoin.getNumJoinFactors();
    List<Integer> sortedFactors =
        factorCostOrdering.immutableSortedCopy(Util.range(nJoinFactors));

    // loop through the factors in sort order, treating the factor as
    // a fact table; analyze the possible semijoins associated with
    // that fact table
    for (int i = 0; i < nJoinFactors; i++) {
      Integer factIdx = sortedFactors.get(i);
      RelNode factRel = chosenSemiJoins[factIdx];
      Map<Integer, LogicalJoin> possibleDimensions =
          possibleSemiJoins.get(factIdx);
      if (possibleDimensions == null) {
        continue;
      }
      double bestScore = 0.0;
      int bestDimIdx = -1;

      // loop through each dimension table associated with the current
      // fact table and analyze the ones that have semijoins with this
      // fact table
      Set<Integer> dimIdxes = possibleDimensions.keySet();
      for (Integer dimIdx : dimIdxes) {
        LogicalJoin semiJoin = possibleDimensions.get(dimIdx);
        if (semiJoin == null) {
          continue;
        }

        // keep track of the dimension table that has the best score
        // for filtering this fact table
        double score =
            computeScore(
                factRel,
                chosenSemiJoins[dimIdx],
                semiJoin);
        if ((score > THRESHOLD_SCORE) && (score > bestScore)) {
          bestDimIdx = dimIdx;
          bestScore = score;
        }
      }

      // if a suitable dimension table has been found, associate it
      // with the fact table in the chosenSemiJoins array; also remove
      // the entry from possibleSemiJoins so we won't chose it again;
      // note that we create the SemiJoin using the chosen semijoins
      // already created for each factor so any chaining of filters will
      // be accounted for
      if (bestDimIdx != -1) {
        int bestDimIdxFinal = bestDimIdx;
        LogicalJoin semiJoin = requireNonNull(possibleDimensions.get(bestDimIdxFinal),
            () -> "possibleDimensions.get(" + bestDimIdxFinal + ") is null");
        LogicalJoin chosenSemiJoin =
            LogicalJoin.create(factRel,
                chosenSemiJoins[bestDimIdx],
                ImmutableList.of(),
                semiJoin.getCondition(),
                ImmutableSet.of(),
                JoinRelType.SEMI);
        chosenSemiJoins[factIdx] = chosenSemiJoin;

        // determine if the dimension table doesn't need to be joined
        // as a result of this semijoin
        removeJoin(multiJoin, chosenSemiJoin, factIdx, bestDimIdx);

        removePossibleSemiJoin(
            possibleDimensions,
            factIdx,
            bestDimIdx);

        // need to also remove the semijoin from the possible
        // semijoins associated with this dimension table, as the
        // semijoin can only be used to filter one table, not both
        removePossibleSemiJoin(
            possibleSemiJoins.get(bestDimIdx),
            bestDimIdx,
            factIdx);
        return true;
      }

      // continue searching on the next fact table if we couldn't find
      // a semijoin for the current fact table
    }

    return false;
  }
Finds the optimal semijoin for filtering the least costly fact table from
among the remaining possible semijoins to choose from. The chosen
semijoin is stored in the chosenSemiJoins array

@param multiJoin join factors being optimized

@return true if a suitable semijoin is found; false otherwise
ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/rules/HiveLoptSemiJoinOptimizer.java