Package sql.optimizers.name

Source Code of sql.optimizers.name.CostEstimator

package sql.optimizers.name;

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

import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Column;
import plan_runner.components.Component;
import plan_runner.components.DataSourceComponent;
import plan_runner.components.EquiJoinComponent;
import plan_runner.components.OperatorComponent;
import sql.estimators.SelingerSelectivityEstimator;
import sql.schema.Schema;
import sql.util.ParserUtil;
import sql.visitors.jsql.SQLVisitor;

/*
* Responsible for computing selectivities, cardinalities and parallelism for NCG._compCost
* Instantiates CostParallelismAssigner
*/
public class CostEstimator {
  private final String _queryName;
  private final SQLVisitor _pq;
  private final Schema _schema;

  // needed because NameCompGen sets parallelism for all the components
  private final CostParallelismAssigner _parAssigner;

  private final Map<String, CostParams> _compCost;
  private final SelingerSelectivityEstimator _selEstimator;

  public CostEstimator(String queryName, Schema schema, SQLVisitor pq,
      Map<String, CostParams> compCost, CostParallelismAssigner parAssigner) {
    _queryName = queryName;
    _pq = pq;
    _schema = schema;
    _compCost = compCost;

    _parAssigner = parAssigner;
    _selEstimator = new SelingerSelectivityEstimator(_queryName, schema, _pq.getTan());
  }

  private double computeHashSelectivity(String leftJoinTableSchemaName,
      String rightJoinTableSchemaName, long leftCardinality, long rightCardinality) {
    final long inputCardinality = leftCardinality + rightCardinality;
    double selectivity;

    if (leftJoinTableSchemaName.equals(rightJoinTableSchemaName))
      // we treat this as a cross-product on which some selections are
      // performed
      // IMPORTANT: selectivity is the output/input rate in the case of
      // EquiJoin
      selectivity = (leftCardinality * rightCardinality) / inputCardinality;
    else {
      double ratio = _schema.getRatio(leftJoinTableSchemaName, rightJoinTableSchemaName);
      if (ratio < 1)
        // if we are joining bigger and smaller relation, the size of
        // join does not decrease
        // it has to be 1
        ratio = 1;
      // in case of bushy plans it's proportion of sizes
      // for lefty plans it's enough to be selectivity of the right parent
      // component (from compCost)
      final double rightSelectivity = ((double) rightCardinality)
          / _schema.getTableSize(rightJoinTableSchemaName);
      selectivity = (leftCardinality * ratio * rightSelectivity) / inputCardinality;
    }
    return selectivity;
  }

  // ***********HELPER methods***********
  private double computeJoinSelectivity(EquiJoinComponent joinComponent,
      List<Expression> joinCondition, long leftCardinality, long rightCardinality) {

    final Component[] parents = joinComponent.getParents();
    double selectivity = 1;

    final List<Column> joinColumns = ParserUtil.getJSQLColumns(joinCondition);
    final List<String> joinCompNames = ParserUtil.getCompNamesFromColumns(joinColumns);

    final List<String> leftJoinTableSchemaNames = getJoinSchemaNames(joinCompNames, parents[0]);
    final List<String> rightJoinTableSchemaNames = getJoinSchemaNames(joinCompNames, parents[1]);

    if (rightJoinTableSchemaNames.size() > 1)
      throw new RuntimeException("Currently, this support only lefty plans!");
    final String rightJoinTableSchemaName = rightJoinTableSchemaNames.get(0);

    int i = 0;
    for (final String leftJoinTableSchemaName : leftJoinTableSchemaNames) {
      double hashSelectivity = computeHashSelectivity(leftJoinTableSchemaName,
          rightJoinTableSchemaName, leftCardinality, rightCardinality);
      if (i > 0 && hashSelectivity > 1)
        // having multiple hashSelectivities means that we have
        // AndCondition between them,
        // so they cannot amplify each other.
        hashSelectivity = 1;
      selectivity *= hashSelectivity;
      i++;
    }

    return selectivity;
  }

  /*
   * @allJoinCompNames - all the component names from the join condition
   * joinCompNames - all the component names from the join condition
   * corresponding to parent
   */
  private List<String> getJoinSchemaNames(List<String> allJoinCompNames, Component parent) {
    final List<String> ancestors = ParserUtil.getSourceNameList(parent);
    final List<String> joinCompNames = ParserUtil.getIntersection(ancestors, allJoinCompNames);

    final List<String> joinSchemaNames = new ArrayList<String>();
    for (final String joinCompName : joinCompNames)
      joinSchemaNames.add(_pq.getTan().getSchemaName(joinCompName));
    return joinSchemaNames;
  }

  // ***********OPERATORS***********
  public void processWhereCost(Component component, Expression whereCompExpr) {
    if (whereCompExpr != null) {
      // this is going to change selectivity
      final String compName = component.getName();
      final CostParams costParams = _compCost.get(compName);
      final double previousSelectivity = costParams.getSelectivity();

      final double selectivity = previousSelectivity * _selEstimator.estimate(whereCompExpr);
      costParams.setSelectivity(selectivity);
    }
  }

  // ***********SOURCES***********
  // for now only cardinalities
  public void setInputParams(DataSourceComponent source) {
    final String compName = source.getName();
    final String schemaName = _pq.getTan().getSchemaName(compName);

    final CostParams costParams = _compCost.get(compName);
    costParams.setCardinality(_schema.getTableSize(schemaName));
  }

  // ***********EquiJoinComponent***********
  public void setInputParams(EquiJoinComponent joinComponent, List<Expression> joinCondition) {
    final CostParams costParams = _compCost.get(joinComponent.getName());
    final Component[] parents = joinComponent.getParents();

    // ********* set initial (join) selectivity and initial cardinality
    final long leftCardinality = _compCost.get(parents[0].getName()).getCardinality();
    final long rightCardinality = _compCost.get(parents[1].getName()).getCardinality();

    // compute
    final long inputCardinality = leftCardinality + rightCardinality;
    final double selectivity = computeJoinSelectivity(joinComponent, joinCondition,
        leftCardinality, rightCardinality);

    // setting
    costParams.setCardinality(inputCardinality);
    costParams.setSelectivity(selectivity);
    // *********
  }

  // ***********OperatorComponent***********
  public void setInputParams(OperatorComponent opComp) {
    final CostParams costParams = _compCost.get(opComp.getName());
    final String parentName = opComp.getParents()[0].getName();

    costParams.setCardinality(_compCost.get(parentName).getCardinality());
    costParams.setSelectivity(1);
  }

  // ***********COMMON***********
  // for now only cardinalities
  private void setOutputParams(Component comp) {
    final CostParams costParams = _compCost.get(comp.getName());
    final long currentCardinality = costParams.getCardinality();
    final double selectivity = costParams.getSelectivity();
    final long cardinality = (long) (selectivity * currentCardinality);
    costParams.setCardinality(cardinality);
  }

  public void setOutputParamsAndPar(DataSourceComponent source) {
    setOutputParams(source);

    _parAssigner.setParallelism(source, _compCost);
    _parAssigner.setBatchSize(source, _compCost); // has to go after
    // parallelism
  }

  public void setOutputParamsAndPar(EquiJoinComponent joinComponent) {
    setOutputParams(joinComponent);

    _parAssigner.setParallelism(joinComponent, _compCost);
    _parAssigner.setBatchSize(joinComponent, _compCost); // has to go after
    // setting
    // parallelism
  }

  public void setOutputParamsAndPar(OperatorComponent opComp) {
    setOutputParams(opComp);

    _parAssigner.setParallelism(opComp, _compCost);
    _parAssigner.setBatchSize(opComp, _compCost);
  }

}
TOP

Related Classes of sql.optimizers.name.CostEstimator

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.