private static List<List<TableScanOperator>> groupTableScanOperators(List<Entry<String, Long>> sortedTables,
      ListMultimap<String, TableScanOperator> tableNameToOps, int batchSize) {
    if (batchSize == -1) {
      return sortedTables.stream().map(entry -> tableNameToOps.get(entry.getKey())).collect(Collectors.toList());
    }

    final List<List<TableScanOperator>> batches = new ArrayList<>();
    for (Entry<String, Long> tablePair : sortedTables) {
      final String tableName = tablePair.getKey();
      final List<TableScanOperator> scans = tableNameToOps.get(tableName);

      final int limit = scans.size();
      int from = 0;
      while (from != limit) {
        final int to = Math.min(limit, from + batchSize);
        // We have to copy the list because it is mutated later
        final List<TableScanOperator> subList = new ArrayList<>(scans.subList(from, to));
        batches.add(subList);
        from = to;
      }
    }

    return batches;
  }
Shared computation optimizer.

<p>Originally, this rule would find scan operators over the same table
in the query plan and merge them if they met some preconditions.
<pre>
 TS   TS             TS
 |    |     -&gt;   /  \
 Op   Op           Op  Op
</pre>
<p>Now the rule has been extended to find opportunities to other operators
downstream, not only a single table scan.

 TS1   TS2    TS1   TS2            TS1   TS2
  |     |      |     |              |     |
  |    RS      |    RS              |    RS
   \   /        \   /       -&gt;    \   /
  MapJoin      MapJoin              MapJoin
     |            |                  /   \
     Op           Op                Op   Op

<p>If the extended version of the optimizer is enabled, it can go beyond
a work boundary to find reutilization opportunities.

<p>The optimization only works with the Tez execution engine.
ql/src/java/org/apache/hadoop/hive/ql/optimizer/SharedWorkOptimizer.java