private void fetchNextGroup(Byte t) throws HiveException {
    if (keyWritables[t] != null) {
      return; // First process the current key.
    }
    if (foundNextKeyGroup[t]) {
      // first promote the next group to be the current group if we reached a
      // new group in the previous fetch
      if (this.nextKeyWritables[t] != null) {
        promoteNextGroupToCandidate(t);
      } else {
        this.keyWritables[t] = null;
        this.candidateStorage[t] = null;
        this.nextGroupStorage[t] = null;
      }
      foundNextKeyGroup[t] = false;
    }
    // for the big table, we only need to promote the next group to the current group.
    if (t == posBigTable) {
      return;
    }

    // for tables other than the big table, we need to fetch more data until reach a new group or
    // done.
    interruptChecker.startAbortChecks(); // Reset the time, we only want to count it in the loop.
    while (!foundNextKeyGroup[t]) {
      if (fetchDone[t]) {
        break;
      }
      fetchOneRow(t);
      try {
        interruptChecker.addRowAndMaybeCheckAbort();
      } catch (InterruptedException e) {
        throw new HiveException(e);
      }
    }
    if (!foundNextKeyGroup[t] && fetchDone[t]) {
      this.nextKeyWritables[t] = null;
    }
  }
Decides if the actual row must be an unmatched row.

Unmatched rows are those which are not part of the inner-join.
The current implementation has issues processing filtered rows in FOJ conditions.
Putting them in a separate group also reduces processing done for them.
ql/src/java/org/apache/hadoop/hive/ql/exec/CommonMergeJoinOperator.java