@Override
    public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
        Object... nodeOutputs) throws SemanticException {
      FileSinkOperator fileSinkOp   = (FileSinkOperator)nd;

      // Has this filesink already been processed
      if (fileSinkOp.getConf().isLinkedFileSink()) {
        return null;
      }

      int size = stack.size();
      int pos = size - 2;
      UnionOperator union = null;

      // Walk the tree. As long as the operators between the union and the filesink
      // do not involve a reducer, and they can be pushed above the union, it makes
      // sense to push them above the union, and remove the union. An interface
      // has been added to the operator 'supportUnionRemoveOptimization' to denote whether
      // this operator can be removed.
      while (pos >= 0) {
        Operator<? extends OperatorDesc> operator =
          (Operator<? extends OperatorDesc>)stack.get(pos);

        // (1) Because we have operator.supportUnionRemoveOptimization() for
        // true only in SEL and FIL operators,
        // this rule will actually only match UNION%(SEL%|FIL%)*FS%
        // (2) The assumption here is that, if
        // operator.getChildOperators().size() > 1, we are going to have
        // multiple FS operators, i.e., multiple inserts.
        // Current implementation does not support this. More details, please
        // see HIVE-9217.
        if (operator.getChildOperators() != null && operator.getChildOperators().size() > 1) {
          return null;
        }
        // Break if it encountered a union
        if (operator instanceof UnionOperator) {
          union = (UnionOperator)operator;
          break;
        }

        if (!operator.supportUnionRemoveOptimization()) {
          return null;
        }
        pos--;
      }

      UnionProcContext ctx = (UnionProcContext) procCtx;
      UnionParseContext uCtx = ctx.getUnionParseContext(union);

      // No need for this if all sub-queries are map-only queries
      // If all the queries are map-only, anyway the query is most optimized
      if ((uCtx != null) && (uCtx.allMapOnlySubQ())) {
        return null;
      }

      pos++;
      pushOperatorsAboveUnion(union, stack, pos);
      return null;
    }
Union followed by no processing.
This is to optimize queries of the type:
select * from (subq1 union all subq2 ...)x;
where at least one of the queries involve a map-reduce job.
There is no need for a union in this scenario - it involves an extra
write and read for the final output without this optimization.
Queries of the form:
  select x.c1 from (subq1 union all subq2 ...)x where filter(x.c2);
can be transformed to:
  select * from (subq1 where filter union all subq2 where filter ...)x;
and then optimized.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/unionproc/UnionProcFactory.java