@Override
    public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx, Object... nodeOutputs)
        throws SemanticException {
      ReduceSinkOperator rop = (ReduceSinkOperator) nd;
      Operator<? extends OperatorDesc> parent = rop.getParentOperators().get(0);
      Statistics parentStats = parent.getStatistics();
      if (parentStats != null) {
        AnnotateStatsProcCtx aspCtx = (AnnotateStatsProcCtx) procCtx;
        HiveConf conf = aspCtx.getConf();
        List<String> outKeyColNames = rop.getConf().getOutputKeyColumnNames();
        List<String> outValueColNames = rop.getConf().getOutputValueColumnNames();
        Map<String, ExprNodeDesc> colExprMap = rop.getColumnExprMap();
        Statistics outStats = parentStats.clone();
        if (satisfyPrecondition(parentStats)) {
          List<ColStatistics> colStats = Lists.newArrayList();
          for (String key : outKeyColNames) {
            String prefixedKey = Utilities.ReduceField.KEY.toString() + "." + key;
            ExprNodeDesc end = colExprMap.get(prefixedKey);
            if (end != null) {
              ColStatistics cs = StatsUtils.getColStatisticsFromExpression(conf, parentStats, end);
              if (cs != null) {
                cs.setColumnName(prefixedKey);
                colStats.add(cs);
              }
            }
          }

          for (String val : outValueColNames) {
            String prefixedVal = Utilities.ReduceField.VALUE.toString() + "." + val;
            ExprNodeDesc end = colExprMap.get(prefixedVal);
            if (end != null) {
              ColStatistics cs = StatsUtils.getColStatisticsFromExpression(conf, parentStats, end);
              if (cs != null) {
                cs.setColumnName(prefixedVal);
                colStats.add(cs);
              }
            }
          }

          outStats.setColumnStats(colStats);
        }

        outStats = applyRuntimeStats(aspCtx.getParseContext().getContext(), outStats, rop);
        rop.setStatistics(outStats);
        if (LOG.isDebugEnabled()) {
          LOG.debug("[0] STATS-" + rop.toString() + ": " + outStats.extendedToString());
        }
      }
      return null;
    }
ReduceSink operator does not change any of the statistics. But it renames
the column statistics from its parent based on the output key and value
column names to make it easy for the downstream operators. This is different
from the default stats which just aggregates and passes along the statistics
without actually renaming based on output schema of the operator.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/stats/annotation/StatsRulesProcFactory.java