Package sql.optimizers.name

Source Code of sql.optimizers.name.NameCostOptimizer

package sql.optimizers.name;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.log4j.Logger;

import plan_runner.components.Component;
import plan_runner.query_plans.QueryPlan;
import plan_runner.utilities.SystemParameters;
import sql.optimizers.Optimizer;
import sql.util.ImproperParallelismException;
import sql.util.ParserUtil;
import sql.visitors.jsql.SQLVisitor;

/*
* For lefty plans, parallelism obtained from cost formula
*/
public class NameCostOptimizer implements Optimizer {
  private static Logger LOG = Logger.getLogger(NameCostOptimizer.class);

  private final SQLVisitor _pq;
  private final Map _map;

  public NameCostOptimizer(Map map) {
    _map = map;
    _pq = ParserUtil.parseQuery(map);
  }

  private void addEquiJoinNotSuboptimal(Component firstComp, Component secondComp,
      NameCompGen ncg, List<NameCompGen> listNcg) {

    boolean isExc = false;
    try {
      ncg.generateEquiJoin(firstComp, secondComp);
    } catch (final ImproperParallelismException exc) {
      final StringBuilder errorMsg = new StringBuilder();
      errorMsg.append(
          "This subplan will never generated the optimal query plan, so it's thrown:")
          .append("\n");
      errorMsg.append(exc.getMessage()).append("\n");
      LOG.info(errorMsg.toString());
      isExc = true;
    }
    if (!isExc)
      // if this subplan is somewhat suboptimal, it's not added to the
      // list
      listNcg.add(ncg);
  }

  /*
   * best is the one with the smallest total nodes used
   */
  private NameCompGen chooseBest(List<NameCompGen> ncgList) {
    if (ncgList.isEmpty()) {
      final String errorMsg = "No query plans can be efficiently executed with specified parallelisms.\n"
          + "Try to reduce DIP_TOTAL_SRC_PAR in config file.";
      LOG.info(errorMsg);
      System.exit(1);
    }

    final int index = getMinTotalParIndex(ncgList);
    return ncgList.get(index);
  }

  @Override
  public QueryPlan generate() {
    final int totalSourcePar = SystemParameters.getInt(_map, "DIP_TOTAL_SRC_PAR");
    final NameCompGenFactory factory = new NameCompGenFactory(_map, _pq.getTan(),
        totalSourcePar);
    final List<String> sourceNames = factory.getParAssigner().getSortedSourceNames();
    final int numSources = sourceNames.size();
    NameCompGen optimal = null;

    // **************creating single-relation plans********************
    if (numSources == 1) {
      optimal = factory.create();
      optimal.generateDataSource(sourceNames.get(0));
    }

    // **************creating 2-way joins********************
    List<NameCompGen> ncgListFirst = new ArrayList<NameCompGen>();
    for (int i = 0; i < numSources; i++) {
      final String firstCompName = sourceNames.get(i);
      final List<String> joinedWith = _pq.getJte().getJoinedWithSingleDir(firstCompName);
      if (joinedWith != null)
        for (final String secondCompName : joinedWith) {
          final NameCompGen ncg = factory.create();
          final Component first = ncg.generateDataSource(firstCompName);
          final Component second = ncg.generateDataSource(secondCompName);
          addEquiJoinNotSuboptimal(first, second, ncg, ncgListFirst);
        }
    }
    if (numSources == 2)
      optimal = chooseBest(ncgListFirst);

    // **************creating multi-way joins********************
    for (int level = 2; level < numSources; level++) {
      List<NameCompGen> ncgListSecond = new ArrayList<NameCompGen>();
      for (int i = 0; i < ncgListFirst.size(); i++) {
        final NameCompGen ncg = ncgListFirst.get(i);
        Component firstComp = ncg.getQueryPlan().getLastComponent();
        final List<String> ancestors = ParserUtil.getSourceNameList(firstComp);
        final List<String> joinedWith = _pq.getJte().getJoinedWith(ancestors);
        for (final String compName : joinedWith) {
          NameCompGen newNcg = ncg;
          if (joinedWith.size() > 1) {
            // doing deepCopy only if there are multiple tables to
            // be joined with
            newNcg = ncg.deepCopy();
            firstComp = newNcg.getQueryPlan().getLastComponent();
          }

          final Component secondComp = newNcg.generateDataSource(compName);
          addEquiJoinNotSuboptimal(firstComp, secondComp, newNcg, ncgListSecond);
        }
      }

      if (level == numSources - 1)
        // last level, chooseOptimal
        optimal = chooseBest(ncgListSecond);
      else
        // filtering - for NCGs with the same ancestor set, choose the
        // one with the smallest totalParallelism
        ncgListSecond = pruneSubplans(ncgListSecond);

      ncgListFirst = ncgListSecond;
    }

    ParserUtil.parallelismToMap(optimal, _map);

    return optimal.getQueryPlan();
  }

  private int getMinTotalPar(List<NameCompGen> ncgList) {
    final int minParIndex = getMinTotalParIndex(ncgList);
    return ParserUtil.getTotalParallelism(ncgList.get(minParIndex));
  }

  private int getMinTotalParIndex(List<NameCompGen> ncgList) {
    int totalPar = ParserUtil.getTotalParallelism(ncgList.get(0));
    int minParIndex = 0;
    for (int i = 1; i < ncgList.size(); i++) {
      final int currentTotalPar = ParserUtil.getTotalParallelism(ncgList.get(i));
      if (currentTotalPar < totalPar) {
        minParIndex = i;
        totalPar = currentTotalPar;
      }
    }
    return minParIndex;
  }

  private List<NameCompGen> pruneSubplans(List<NameCompGen> ncgList) {
    final Map<Set<String>, List<NameCompGen>> collection = new HashMap<Set<String>, List<NameCompGen>>();

    // filling in the collection with the appropriate key-value structure
    for (final NameCompGen ncg : ncgList) {
      final Set<String> ancestors = ParserUtil.getSourceNameSet(ncg.getQueryPlan()
          .getLastComponent());
      ParserUtil.addToCollection(ancestors, ncg, collection);
    }

    final List<NameCompGen> pruned = new ArrayList<NameCompGen>();
    // for each key(which is set of ancestors) choose only the best one
    for (final Map.Entry<Set<String>, List<NameCompGen>> entrySet : collection.entrySet()) {
      final List<NameCompGen> valueList = entrySet.getValue();

      // all the equivalent plans having minimum totalParallelism are
      // added
      // there might be muptiple of them
      final int minTotalPar = getMinTotalPar(valueList);
      for (final NameCompGen ncg : valueList) {
        final int totalPar = ParserUtil.getTotalParallelism(ncg);
        if (totalPar == minTotalPar)
          pruned.add(ncg);
      }
    }
    return pruned;
  }

}
TOP

Related Classes of sql.optimizers.name.NameCostOptimizer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.