diff --git a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/cost/HiveVolcanoPlanner.java b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/cost/HiveVolcanoPlanner.java index fbf2202679..23ff518ada 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/cost/HiveVolcanoPlanner.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/optimizer/calcite/cost/HiveVolcanoPlanner.java @@ -23,15 +23,15 @@ import org.apache.calcite.plan.Convention; import org.apache.calcite.plan.ConventionTraitDef; import org.apache.calcite.plan.RelOptCost; -import org.apache.calcite.plan.RelOptCostImpl; import org.apache.calcite.plan.RelOptPlanner; +import org.apache.calcite.plan.RelOptUtil; import org.apache.calcite.plan.volcano.RelSubset; import org.apache.calcite.plan.volcano.VolcanoPlanner; import org.apache.calcite.rel.RelCollationTraitDef; import org.apache.calcite.rel.RelNode; import org.apache.calcite.rel.core.TableScan; import org.apache.calcite.rel.metadata.RelMetadataQuery; -import org.apache.commons.math3.util.FastMath; +import org.apache.calcite.util.Util; import org.apache.hadoop.hive.ql.optimizer.calcite.HiveConfPlannerContext; import org.apache.hadoop.hive.ql.optimizer.calcite.HivePlannerContext; import org.apache.hadoop.hive.ql.optimizer.calcite.RelOptHiveTable; @@ -48,7 +48,6 @@ private static final boolean ENABLE_COLLATION_TRAIT = true; private final boolean isHeuristic; - private static final double FACTOR = 0.2d; /** Creates a HiveVolcanoPlanner. */ @@ -96,7 +95,9 @@ public void registerClass(RelNode node) { public RelOptCost getCost(RelNode rel, RelMetadataQuery mq) { assert rel != null : "pre-condition: rel != null"; if (rel instanceof RelSubset) { - return getCost(((RelSubset) rel).getBest(), mq); + // Get cost of the subset, best rel may have been chosen or not + RelSubset subset = (RelSubset) rel; + return getCost(Util.first(subset.getBest(), subset.getOriginal()), mq); } if (rel.getTraitSet().getTrait(ConventionTraitDef.INSTANCE) == Convention.NONE) { @@ -121,15 +122,19 @@ public RelOptCost getCost(RelNode rel, RelMetadataQuery mq) { } } if (isHeuristic && usesMaterializedViews) { - cost = costFactory.makeTinyCost(); + // If a child of this expression uses a materialized view, + // then we decrease its cost by a certain factor. This is + // useful for e.g. partial rewritings, where a part of plan + // does not use the materialization, but we still want to + // decrease its cost so it is chosen instead of the original + // plan + cost = cost.multiplyBy(RelOptUtil.EPSILON); + if (!costFactory.makeZeroCost().isLt(cost)) { + // cost must be positive, so nudge it + cost = costFactory.makeTinyCost(); + } for (RelNode input : rel.getInputs()) { - // If a child of this expression uses a materialized view, - // then we decrease its cost by a certain factor. This is - // useful for e.g. partial rewritings, where a part of plan - // does not use the materialization, but we still want to - // decrease its cost so it is chosen instead of the original - // plan - cost = cost.plus(getCost(input, mq).multiplyBy(FACTOR)); + cost = cost.plus(getCost(input, mq)); } } else { // No materialized view or not heuristic approach, normal costing