Search in sources :

Example 1 with DrillAggregateRel

use of org.apache.drill.exec.planner.logical.DrillAggregateRel in project drill by apache.

the class StreamAggPrule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final DrillAggregateRel aggregate = (DrillAggregateRel) call.rel(0);
    RelNode input = aggregate.getInput();
    final RelCollation collation = getCollation(aggregate);
    RelTraitSet traits = null;
    if (aggregate.containsDistinctCall()) {
        // currently, don't use StreamingAggregate if any of the logical aggrs contains DISTINCT
        return;
    }
    try {
        if (aggregate.getGroupSet().isEmpty()) {
            DrillDistributionTrait singleDist = DrillDistributionTrait.SINGLETON;
            final RelTraitSet singleDistTrait = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(singleDist);
            if (create2PhasePlan(call, aggregate)) {
                traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL);
                RelNode convertedInput = convert(input, traits);
                new SubsetTransformer<DrillAggregateRel, InvalidRelException>(call) {

                    @Override
                    public RelNode convertChild(final DrillAggregateRel join, final RelNode rel) throws InvalidRelException {
                        DrillDistributionTrait toDist = rel.getTraitSet().getTrait(DrillDistributionTraitDef.INSTANCE);
                        RelTraitSet traits = newTraitSet(Prel.DRILL_PHYSICAL, toDist);
                        RelNode newInput = convert(rel, traits);
                        StreamAggPrel phase1Agg = new StreamAggPrel(aggregate.getCluster(), traits, newInput, aggregate.indicator, aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList(), OperatorPhase.PHASE_1of2);
                        UnionExchangePrel exch = new UnionExchangePrel(phase1Agg.getCluster(), singleDistTrait, phase1Agg);
                        return new StreamAggPrel(aggregate.getCluster(), singleDistTrait, exch, aggregate.indicator, aggregate.getGroupSet(), aggregate.getGroupSets(), phase1Agg.getPhase2AggCalls(), OperatorPhase.PHASE_2of2);
                    }
                }.go(aggregate, convertedInput);
            } else {
                createTransformRequest(call, aggregate, input, singleDistTrait);
            }
        } else {
            // hash distribute on all grouping keys
            final DrillDistributionTrait distOnAllKeys = new DrillDistributionTrait(DrillDistributionTrait.DistributionType.HASH_DISTRIBUTED, ImmutableList.copyOf(getDistributionField(aggregate, true)));
            traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(collation).plus(distOnAllKeys);
            createTransformRequest(call, aggregate, input, traits);
            // hash distribute on one grouping key
            DrillDistributionTrait distOnOneKey = new DrillDistributionTrait(DrillDistributionTrait.DistributionType.HASH_DISTRIBUTED, ImmutableList.copyOf(getDistributionField(aggregate, false)));
            traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(collation).plus(distOnOneKey);
            if (create2PhasePlan(call, aggregate)) {
                traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL);
                RelNode convertedInput = convert(input, traits);
                new SubsetTransformer<DrillAggregateRel, InvalidRelException>(call) {

                    @Override
                    public RelNode convertChild(final DrillAggregateRel aggregate, final RelNode rel) throws InvalidRelException {
                        DrillDistributionTrait toDist = rel.getTraitSet().getTrait(DrillDistributionTraitDef.INSTANCE);
                        RelTraitSet traits = newTraitSet(Prel.DRILL_PHYSICAL, collation, toDist);
                        RelNode newInput = convert(rel, traits);
                        StreamAggPrel phase1Agg = new StreamAggPrel(aggregate.getCluster(), traits, newInput, aggregate.indicator, aggregate.getGroupSet(), aggregate.getGroupSets(), aggregate.getAggCallList(), OperatorPhase.PHASE_1of2);
                        int numEndPoints = PrelUtil.getSettings(phase1Agg.getCluster()).numEndPoints();
                        HashToMergeExchangePrel exch = new HashToMergeExchangePrel(phase1Agg.getCluster(), phase1Agg.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(distOnAllKeys), phase1Agg, ImmutableList.copyOf(getDistributionField(aggregate, true)), collation, numEndPoints);
                        return new StreamAggPrel(aggregate.getCluster(), exch.getTraitSet(), exch, aggregate.indicator, aggregate.getGroupSet(), aggregate.getGroupSets(), phase1Agg.getPhase2AggCalls(), OperatorPhase.PHASE_2of2);
                    }
                }.go(aggregate, convertedInput);
            }
        }
    } catch (InvalidRelException e) {
        tracer.warning(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) RelCollation(org.apache.calcite.rel.RelCollation) RelNode(org.apache.calcite.rel.RelNode) DrillAggregateRel(org.apache.drill.exec.planner.logical.DrillAggregateRel) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Example 2 with DrillAggregateRel

use of org.apache.drill.exec.planner.logical.DrillAggregateRel in project drill by apache.

the class JoinUtils method isScalarSubquery.

/**
   * Utility method to check if a subquery (represented by its root RelNode) is provably scalar. Currently
   * only aggregates with no group-by are considered scalar. In the future, this method should be generalized
   * to include more cases and reconciled with Calcite's notion of scalar.
   * @param root The root RelNode to be examined
   * @return True if the root rel or its descendant is scalar, False otherwise
   */
public static boolean isScalarSubquery(RelNode root) {
    DrillAggregateRel agg = null;
    RelNode currentrel = root;
    while (agg == null && currentrel != null) {
        if (currentrel instanceof DrillAggregateRel) {
            agg = (DrillAggregateRel) currentrel;
        } else if (currentrel instanceof RelSubset) {
            currentrel = ((RelSubset) currentrel).getBest();
        } else if (currentrel.getInputs().size() == 1) {
            // If the rel is not an aggregate or RelSubset, but is a single-input rel (could be Project,
            // Filter, Sort etc.), check its input
            currentrel = currentrel.getInput(0);
        } else {
            break;
        }
    }
    if (agg != null) {
        if (agg.getGroupSet().isEmpty()) {
            return true;
        }
    }
    return false;
}
Also used : RelNode(org.apache.calcite.rel.RelNode) DrillAggregateRel(org.apache.drill.exec.planner.logical.DrillAggregateRel) RelSubset(org.apache.calcite.plan.volcano.RelSubset)

Example 3 with DrillAggregateRel

use of org.apache.drill.exec.planner.logical.DrillAggregateRel in project drill by apache.

the class ConvertCountToDirectScan method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final DrillAggregateRel agg = (DrillAggregateRel) call.rel(0);
    final DrillScanRel scan = (DrillScanRel) call.rel(call.rels.length - 1);
    final DrillProjectRel proj = call.rels.length == 3 ? (DrillProjectRel) call.rel(1) : null;
    final GroupScan oldGrpScan = scan.getGroupScan();
    final PlannerSettings settings = PrelUtil.getPlannerSettings(call.getPlanner());
    //    4) No distinct agg call.
    if (!(oldGrpScan.getScanStats(settings).getGroupScanProperty().hasExactRowCount() && agg.getGroupCount() == 0 && agg.getAggCallList().size() == 1 && !agg.containsDistinctCall())) {
        return;
    }
    AggregateCall aggCall = agg.getAggCallList().get(0);
    if (aggCall.getAggregation().getName().equals("COUNT")) {
        long cnt = 0;
        //  count(Not-null-input) ==> rowCount
        if (aggCall.getArgList().isEmpty() || (aggCall.getArgList().size() == 1 && !agg.getInput().getRowType().getFieldList().get(aggCall.getArgList().get(0).intValue()).getType().isNullable())) {
            cnt = (long) oldGrpScan.getScanStats(settings).getRecordCount();
        } else if (aggCall.getArgList().size() == 1) {
            // count(columnName) ==> Agg ( Scan )) ==> columnValueCount
            int index = aggCall.getArgList().get(0);
            if (proj != null) {
                if (proj.getProjects().get(index) instanceof RexInputRef) {
                    index = ((RexInputRef) proj.getProjects().get(index)).getIndex();
                } else {
                    // do not apply for all other cases.
                    return;
                }
            }
            String columnName = scan.getRowType().getFieldNames().get(index).toLowerCase();
            cnt = oldGrpScan.getColumnValueCount(SchemaPath.getSimplePath(columnName));
            if (cnt == GroupScan.NO_COLUMN_STATS) {
                // if column stats are not available don't apply this rule
                return;
            }
        } else {
            // do nothing.
            return;
        }
        RelDataType scanRowType = getCountDirectScanRowType(agg.getCluster().getTypeFactory());
        final ScanPrel newScan = ScanPrel.create(scan, scan.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(DrillDistributionTrait.SINGLETON), getCountDirectScan(cnt), scanRowType);
        List<RexNode> exprs = Lists.newArrayList();
        exprs.add(RexInputRef.of(0, scanRowType));
        final ProjectPrel newProj = new ProjectPrel(agg.getCluster(), agg.getTraitSet().plus(Prel.DRILL_PHYSICAL).plus(DrillDistributionTrait.SINGLETON), newScan, exprs, agg.getRowType());
        call.transformTo(newProj);
    }
}
Also used : DrillScanRel(org.apache.drill.exec.planner.logical.DrillScanRel) DrillProjectRel(org.apache.drill.exec.planner.logical.DrillProjectRel) DrillAggregateRel(org.apache.drill.exec.planner.logical.DrillAggregateRel) RelDataType(org.apache.calcite.rel.type.RelDataType) DirectGroupScan(org.apache.drill.exec.store.direct.DirectGroupScan) GroupScan(org.apache.drill.exec.physical.base.GroupScan) AggregateCall(org.apache.calcite.rel.core.AggregateCall) RexInputRef(org.apache.calcite.rex.RexInputRef) RexNode(org.apache.calcite.rex.RexNode)

Example 4 with DrillAggregateRel

use of org.apache.drill.exec.planner.logical.DrillAggregateRel in project drill by apache.

the class HashAggPrule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    if (!PrelUtil.getPlannerSettings(call.getPlanner()).isHashAggEnabled()) {
        return;
    }
    final DrillAggregateRel aggregate = (DrillAggregateRel) call.rel(0);
    final RelNode input = call.rel(1);
    if (aggregate.containsDistinctCall() || aggregate.getGroupCount() == 0) {
        // if there are no grouping keys
        return;
    }
    RelTraitSet traits = null;
    try {
        if (aggregate.getGroupSet().isEmpty()) {
            DrillDistributionTrait singleDist = DrillDistributionTrait.SINGLETON;
            traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(singleDist);
            createTransformRequest(call, aggregate, input, traits);
        } else {
            // hash distribute on all grouping keys
            DrillDistributionTrait distOnAllKeys = new DrillDistributionTrait(DrillDistributionTrait.DistributionType.HASH_DISTRIBUTED, ImmutableList.copyOf(getDistributionField(aggregate, true)));
            traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(distOnAllKeys);
            createTransformRequest(call, aggregate, input, traits);
            // hash distribute on single grouping key
            DrillDistributionTrait distOnOneKey = new DrillDistributionTrait(DrillDistributionTrait.DistributionType.HASH_DISTRIBUTED, ImmutableList.copyOf(getDistributionField(aggregate, false)));
            traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL).plus(distOnOneKey);
            createTransformRequest(call, aggregate, input, traits);
            if (create2PhasePlan(call, aggregate)) {
                traits = call.getPlanner().emptyTraitSet().plus(Prel.DRILL_PHYSICAL);
                RelNode convertedInput = convert(input, traits);
                new TwoPhaseSubset(call, distOnAllKeys).go(aggregate, convertedInput);
            }
        }
    } catch (InvalidRelException e) {
        tracer.warning(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) RelNode(org.apache.calcite.rel.RelNode) DrillAggregateRel(org.apache.drill.exec.planner.logical.DrillAggregateRel) RelTraitSet(org.apache.calcite.plan.RelTraitSet)

Aggregations

DrillAggregateRel (org.apache.drill.exec.planner.logical.DrillAggregateRel)4 RelNode (org.apache.calcite.rel.RelNode)3 RelTraitSet (org.apache.calcite.plan.RelTraitSet)2 InvalidRelException (org.apache.calcite.rel.InvalidRelException)2 RelSubset (org.apache.calcite.plan.volcano.RelSubset)1 RelCollation (org.apache.calcite.rel.RelCollation)1 AggregateCall (org.apache.calcite.rel.core.AggregateCall)1 RelDataType (org.apache.calcite.rel.type.RelDataType)1 RexInputRef (org.apache.calcite.rex.RexInputRef)1 RexNode (org.apache.calcite.rex.RexNode)1 GroupScan (org.apache.drill.exec.physical.base.GroupScan)1 DrillProjectRel (org.apache.drill.exec.planner.logical.DrillProjectRel)1 DrillScanRel (org.apache.drill.exec.planner.logical.DrillScanRel)1 DirectGroupScan (org.apache.drill.exec.store.direct.DirectGroupScan)1