private static int estimateNumBuckets(JoinOperator joinOp, boolean useOpTraits) {
    int numBuckets = -1;
    int estimatedBuckets = -1;

    for (Operator<? extends OperatorDesc>parentOp : joinOp.getParentOperators()) {
      if (!(parentOp instanceof ReduceSinkOperator)) {
        continue;
      }

      final OpTraits parentOpTraits = parentOp.getOpTraits();
      numBuckets = Math.max(numBuckets, parentOpTraits.getNumBuckets());

      if (parentOpTraits.hasCustomBucketFunction()) {
        Preconditions.checkState(parentOpTraits.getCustomBucketFunctions().size() == 1);
        numBuckets = Math.max(numBuckets, parentOpTraits.getCustomBucketFunctions().get(0).getNumBuckets());
      }

      if (!useOpTraits) {
        ReduceSinkOperator rs = (ReduceSinkOperator) parentOp;
        estimatedBuckets = Math.max(estimatedBuckets, rs.getConf().getNumReducers());
      }
    }

    if (!useOpTraits) {
      // Ignore the value we got from OpTraits.
      // The logic below will fall back to the estimate from numReducers
      numBuckets = -1;
    }

    if (numBuckets <= 0) {
      numBuckets = estimatedBuckets;
      if (numBuckets <= 0) {
        numBuckets = 1;
      }
    }

    return numBuckets;
  }
Estimate the number of buckets in the join, using the parent operators' OpTraits and/or
parent operators' number of reducers
@param joinOp
@param useOpTraits  Whether OpTraits should be used for the estimate.
@return
ql/src/java/org/apache/hadoop/hive/ql/optimizer/ConvertJoinMapJoin.java