Search in sources :

Example 26 with LogicalJoin

use of org.apache.calcite.rel.logical.LogicalJoin in project drill by apache.

the class DrillJoinRelBase method estimateRowCount.

@Override
public double estimateRowCount(RelMetadataQuery mq) {
    if (this.condition.isAlwaysTrue()) {
        return joinRowFactor * this.getLeft().estimateRowCount(mq) * this.getRight().estimateRowCount(mq);
    }
    LogicalJoin jr = LogicalJoin.create(this.getLeft(), this.getRight(), this.getCondition(), this.getVariablesSet(), this.getJoinType());
    if (// Statistics present for left and right side of the join
    !DrillRelOptUtil.guessRows(this) && jr.getJoinType() == JoinRelType.INNER) {
        List<Pair<Integer, Integer>> joinConditions = DrillRelOptUtil.analyzeSimpleEquiJoin((Join) jr);
        if (joinConditions.size() > 0) {
            List<Integer> leftSide = new ArrayList<>();
            List<Integer> rightSide = new ArrayList<>();
            for (Pair<Integer, Integer> condition : joinConditions) {
                leftSide.add(condition.left);
                rightSide.add(condition.right);
            }
            ImmutableBitSet leq = ImmutableBitSet.of(leftSide);
            ImmutableBitSet req = ImmutableBitSet.of(rightSide);
            Double ldrc = mq.getDistinctRowCount(this.getLeft(), leq, null);
            Double rdrc = mq.getDistinctRowCount(this.getRight(), req, null);
            Double lrc = mq.getRowCount(this.getLeft());
            Double rrc = mq.getRowCount(this.getRight());
            if (ldrc != null && rdrc != null && lrc != null && rrc != null) {
                // Join cardinality = (lrc * rrc) / Math.max(ldrc, rdrc). Avoid overflow by dividing earlier
                return (lrc / Math.max(ldrc, rdrc)) * rrc;
            }
        }
    }
    return joinRowFactor * Math.max(mq.getRowCount(this.getLeft()), mq.getRowCount(this.getRight()));
}
Also used : ImmutableBitSet(org.apache.calcite.util.ImmutableBitSet) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) ArrayList(java.util.ArrayList) Pair(org.apache.calcite.util.Pair)

Example 27 with LogicalJoin

use of org.apache.calcite.rel.logical.LogicalJoin in project drill by apache.

the class DrillJoinRule method onMatch.

@Override
public void onMatch(RelOptRuleCall call) {
    final LogicalJoin join = call.rel(0);
    final RelNode left = join.getLeft();
    final RelNode right = join.getRight();
    final RelTraitSet traits = join.getTraitSet().plus(DrillRel.DRILL_LOGICAL);
    final RelNode convertedLeft = convert(left, left.getTraitSet().plus(DrillRel.DRILL_LOGICAL).simplify());
    final RelNode convertedRight = convert(right, right.getTraitSet().plus(DrillRel.DRILL_LOGICAL).simplify());
    List<Integer> leftKeys = Lists.newArrayList();
    List<Integer> rightKeys = Lists.newArrayList();
    List<Boolean> filterNulls = Lists.newArrayList();
    boolean addFilter = false;
    RexNode origJoinCondition = join.getCondition();
    RexNode newJoinCondition = origJoinCondition;
    RexNode remaining = RelOptUtil.splitJoinCondition(convertedLeft, convertedRight, origJoinCondition, leftKeys, rightKeys, filterNulls);
    boolean hasEquijoins = leftKeys.size() == rightKeys.size() && leftKeys.size() > 0;
    // For OUTER join, pulling up a non-eqivjoin filter will lead to incorrectly discarding qualified rows.
    if (!remaining.isAlwaysTrue()) {
        if (hasEquijoins && join.getJoinType() == JoinRelType.INNER) {
            addFilter = true;
            newJoinCondition = buildJoinCondition(convertedLeft, convertedRight, leftKeys, rightKeys, filterNulls, join.getCluster().getRexBuilder());
        }
    } else {
        newJoinCondition = buildJoinCondition(convertedLeft, convertedRight, leftKeys, rightKeys, filterNulls, join.getCluster().getRexBuilder());
    }
    try {
        if (join.isSemiJoin()) {
            RelNode joinRel = new DrillSemiJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, newJoinCondition, leftKeys, rightKeys);
            call.transformTo(joinRel);
            return;
        }
        if (!addFilter) {
            RelNode joinRel = new DrillJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, newJoinCondition, join.getJoinType(), leftKeys, rightKeys);
            call.transformTo(joinRel);
        } else {
            RelNode joinRel = new DrillJoinRel(join.getCluster(), traits, convertedLeft, convertedRight, newJoinCondition, join.getJoinType(), leftKeys, rightKeys);
            call.transformTo(new DrillFilterRel(join.getCluster(), traits, joinRel, remaining));
        }
    } catch (InvalidRelException e) {
        tracer.warn(e.toString());
    }
}
Also used : InvalidRelException(org.apache.calcite.rel.InvalidRelException) RelTraitSet(org.apache.calcite.plan.RelTraitSet) RelNode(org.apache.calcite.rel.RelNode) LogicalJoin(org.apache.calcite.rel.logical.LogicalJoin) RexNode(org.apache.calcite.rex.RexNode)

Aggregations

LogicalJoin (org.apache.calcite.rel.logical.LogicalJoin)27 RelNode (org.apache.calcite.rel.RelNode)20 RexNode (org.apache.calcite.rex.RexNode)14 LogicalProject (org.apache.calcite.rel.logical.LogicalProject)13 ArrayList (java.util.ArrayList)8 LogicalFilter (org.apache.calcite.rel.logical.LogicalFilter)8 TableScan (org.apache.calcite.rel.core.TableScan)5 LogicalTableScan (org.apache.calcite.rel.logical.LogicalTableScan)5 RelDataType (org.apache.calcite.rel.type.RelDataType)5 RelTraitSet (org.apache.calcite.plan.RelTraitSet)4 InvalidRelException (org.apache.calcite.rel.InvalidRelException)4 Join (org.apache.calcite.rel.core.Join)4 RelDataTypeField (org.apache.calcite.rel.type.RelDataTypeField)4 RexBuilder (org.apache.calcite.rex.RexBuilder)4 RexInputRef (org.apache.calcite.rex.RexInputRef)4 ImmutableBitSet (org.apache.calcite.util.ImmutableBitSet)4 RelOptCluster (org.apache.calcite.plan.RelOptCluster)3 RelRoot (org.apache.calcite.rel.RelRoot)3 JoinRelType (org.apache.calcite.rel.core.JoinRelType)3 LogicalAggregate (org.apache.calcite.rel.logical.LogicalAggregate)3