Search in sources :

Example 21 with AbstractBinaryJoinOperator

use of org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator in project asterixdb by apache.

the class RemoveUnusedOneToOneEquiJoinRule method removeJoinFromInputBranch.

private int removeJoinFromInputBranch(Mutable<ILogicalOperator> opRef) throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    if (op.getOperatorTag() != LogicalOperatorTag.INNERJOIN) {
        return -1;
    }
    AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) op;
    // Make sure the join is an equi-join.
    if (!isEquiJoin(joinOp.getCondition())) {
        return -1;
    }
    int unusedJoinBranchIndex = -1;
    for (int i = 0; i < joinOp.getInputs().size(); i++) {
        liveVars.clear();
        VariableUtilities.getLiveVariables(joinOp.getInputs().get(i).getValue(), liveVars);
        if (liveVars.isEmpty()) {
            // The branch does not produce any variable, i.e., it only contains an empty tuple source.
            return i;
        }
        liveVars.retainAll(parentsUsedVars);
        if (liveVars.isEmpty()) {
            // None of the live variables from this branch are used by its parents.
            unusedJoinBranchIndex = i;
            break;
        }
    }
    if (unusedJoinBranchIndex < 0) {
        // The variables from both branches are used in the upstream plan. We cannot remove this join.
        return -1;
    }
    // Check whether one of the join branches is unused.
    usedVars.clear();
    VariableUtilities.getUsedVariables(joinOp, usedVars);
    // Check whether all used variables originate from primary keys of exactly the same dataset.
    // Collect a list of datascans whose primary key variables are used in the join condition.
    gatherProducingDataScans(opRef, usedVars, dataScans);
    if (dataScans.size() < 2) {
        // Either branch does not use its primary key in the join condition.
        return -1;
    }
    // only used primary key variables of those datascans.
    for (int i = 0; i < dataScans.size(); i++) {
        if (i > 0) {
            DatasetDataSource prevAqlDataSource = (DatasetDataSource) dataScans.get(i - 1).getDataSource();
            DatasetDataSource currAqlDataSource = (DatasetDataSource) dataScans.get(i).getDataSource();
            if (!prevAqlDataSource.getDataset().equals(currAqlDataSource.getDataset())) {
                return -1;
            }
        }
        // Remove from the used variables all the primary key vars of this dataset.
        fillPKVars(dataScans.get(i), pkVars);
        usedVars.removeAll(pkVars);
    }
    if (!usedVars.isEmpty()) {
        // keys from datasource scans of the same dataset.
        return -1;
    }
    // We expect the post-plan will NOT prune the join part derived from A.
    if (unusedJoinBranchIndex >= 0 && isSelectionAboveDataScan(opRef.getValue().getInputs().get(unusedJoinBranchIndex))) {
        unusedJoinBranchIndex = -1;
    }
    return unusedJoinBranchIndex;
}
Also used : AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) DatasetDataSource(org.apache.asterix.metadata.declared.DatasetDataSource) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)

Example 22 with AbstractBinaryJoinOperator

use of org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator in project asterixdb by apache.

the class BTreeAccessMethod method applyJoinPlanTransformation.

@Override
public boolean applyJoinPlanTransformation(Mutable<ILogicalOperator> joinRef, OptimizableOperatorSubTree leftSubTree, OptimizableOperatorSubTree rightSubTree, Index chosenIndex, AccessMethodAnalysisContext analysisCtx, IOptimizationContext context, boolean isLeftOuterJoin, boolean hasGroupBy) throws AlgebricksException {
    AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) joinRef.getValue();
    Mutable<ILogicalExpression> conditionRef = joinOp.getCondition();
    // Determine if the index is applicable on the left or right side
    // (if both, we arbitrarily prefer the left side).
    Dataset dataset = analysisCtx.getDatasetFromIndexDatasetMap(chosenIndex);
    OptimizableOperatorSubTree indexSubTree;
    OptimizableOperatorSubTree probeSubTree;
    // The following is just a sanity check.
    if (rightSubTree.hasDataSourceScan() && dataset.getDatasetName().equals(rightSubTree.getDataset().getDatasetName())) {
        indexSubTree = rightSubTree;
        probeSubTree = leftSubTree;
    } else {
        return false;
    }
    LogicalVariable newNullPlaceHolderVar = null;
    if (isLeftOuterJoin) {
        //get a new null place holder variable that is the first field variable of the primary key
        //from the indexSubTree's datasourceScanOp
        newNullPlaceHolderVar = indexSubTree.getDataSourceVariables().get(0);
    }
    ILogicalOperator primaryIndexUnnestOp = createSecondaryToPrimaryPlan(conditionRef, indexSubTree, probeSubTree, chosenIndex, analysisCtx, true, isLeftOuterJoin, true, context);
    if (primaryIndexUnnestOp == null) {
        return false;
    }
    if (isLeftOuterJoin && hasGroupBy) {
        //reset the null place holder variable
        AccessMethodUtils.resetLOJNullPlaceholderVariableInGroupByOp(analysisCtx, newNullPlaceHolderVar, context);
    }
    // If there are conditions left, add a new select operator on top.
    indexSubTree.getDataSourceRef().setValue(primaryIndexUnnestOp);
    if (conditionRef.getValue() != null) {
        SelectOperator topSelect = new SelectOperator(conditionRef, isLeftOuterJoin, newNullPlaceHolderVar);
        topSelect.getInputs().add(indexSubTree.getRootRef());
        topSelect.setExecutionMode(ExecutionMode.LOCAL);
        context.computeAndSetTypeEnvironmentForOperator(topSelect);
        // Replace the original join with the new subtree rooted at the select op.
        joinRef.setValue(topSelect);
    } else {
        joinRef.setValue(indexSubTree.getRootRef().getValue());
    }
    return true;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator) Dataset(org.apache.asterix.metadata.entities.Dataset) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)

Example 23 with AbstractBinaryJoinOperator

use of org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator in project asterixdb by apache.

the class InvertedIndexAccessMethod method createPanicNestedLoopJoinPlan.

private Mutable<ILogicalOperator> createPanicNestedLoopJoinPlan(Mutable<ILogicalOperator> joinRef, OptimizableOperatorSubTree indexSubTree, OptimizableOperatorSubTree probeSubTree, IOptimizableFuncExpr optFuncExpr, Index chosenIndex, Map<LogicalVariable, LogicalVariable> panicVarMap, IOptimizationContext context) throws AlgebricksException {
    LogicalVariable inputSearchVar = getInputSearchVar(optFuncExpr, indexSubTree);
    // We split the plan into two "branches", and add selections on each side.
    AbstractLogicalOperator replicateOp = new ReplicateOperator(2);
    replicateOp.getInputs().add(new MutableObject<ILogicalOperator>(probeSubTree.getRoot()));
    replicateOp.setExecutionMode(ExecutionMode.PARTITIONED);
    context.computeAndSetTypeEnvironmentForOperator(replicateOp);
    // Create select ops for removing tuples that are filterable and not filterable, respectively.
    IVariableTypeEnvironment probeTypeEnv = context.getOutputTypeEnvironment(probeSubTree.getRoot());
    IAType inputSearchVarType;
    if (chosenIndex.isEnforcingKeyFileds()) {
        inputSearchVarType = optFuncExpr.getFieldType(optFuncExpr.findLogicalVar(inputSearchVar));
    } else {
        inputSearchVarType = (IAType) probeTypeEnv.getVarType(inputSearchVar);
    }
    Mutable<ILogicalOperator> isFilterableSelectOpRef = new MutableObject<ILogicalOperator>();
    Mutable<ILogicalOperator> isNotFilterableSelectOpRef = new MutableObject<ILogicalOperator>();
    createIsFilterableSelectOps(replicateOp, inputSearchVar, inputSearchVarType, optFuncExpr, chosenIndex, context, isFilterableSelectOpRef, isNotFilterableSelectOpRef);
    List<LogicalVariable> originalLiveVars = new ArrayList<LogicalVariable>();
    VariableUtilities.getLiveVariables(indexSubTree.getRoot(), originalLiveVars);
    // Copy the scan subtree in indexSubTree.
    LogicalOperatorDeepCopyWithNewVariablesVisitor deepCopyVisitor = new LogicalOperatorDeepCopyWithNewVariablesVisitor(context, context);
    ILogicalOperator scanSubTree = deepCopyVisitor.deepCopy(indexSubTree.getRoot());
    Map<LogicalVariable, LogicalVariable> copyVarMap = deepCopyVisitor.getInputToOutputVariableMapping();
    panicVarMap.putAll(copyVarMap);
    List<LogicalVariable> copyLiveVars = new ArrayList<LogicalVariable>();
    VariableUtilities.getLiveVariables(scanSubTree, copyLiveVars);
    // Replace the inputs of the given join op, and replace variables in its
    // condition since we deep-copied one of the scanner subtrees which
    // changed variables.
    AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) joinRef.getValue();
    for (Map.Entry<LogicalVariable, LogicalVariable> entry : copyVarMap.entrySet()) {
        joinOp.getCondition().getValue().substituteVar(entry.getKey(), entry.getValue());
    }
    joinOp.getInputs().clear();
    joinOp.getInputs().add(new MutableObject<ILogicalOperator>(scanSubTree));
    // Make sure that the build input (which may be materialized causing blocking) comes from
    // the split+select, otherwise the plan will have a deadlock.
    joinOp.getInputs().add(isNotFilterableSelectOpRef);
    context.computeAndSetTypeEnvironmentForOperator(joinOp);
    // Return the new root of the probeSubTree.
    return isFilterableSelectOpRef;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) ReplicateOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.ReplicateOperator) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator) LogicalOperatorDeepCopyWithNewVariablesVisitor(org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.LogicalOperatorDeepCopyWithNewVariablesVisitor) Map(java.util.Map) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) IVariableTypeEnvironment(org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment) IAType(org.apache.asterix.om.types.IAType) MutableObject(org.apache.commons.lang3.mutable.MutableObject)

Example 24 with AbstractBinaryJoinOperator

use of org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator in project asterixdb by apache.

the class InlineLeftNtsInSubplanJoinFlatteningVisitor method visitInnerJoinOperator.

@Override
public ILogicalOperator visitInnerJoinOperator(InnerJoinOperator op, Void arg) throws AlgebricksException {
    hasJoinAncestor = true;
    boolean needToSwitch = false;
    for (int i = 0; i < op.getInputs().size(); ++i) {
        // Deals with single input operators.
        ILogicalOperator newChild = op.getInputs().get(i).getValue().accept(this, null);
        op.getInputs().get(i).setValue(newChild);
        if (i == 1) {
            needToSwitch = true;
        }
        if (rewritten) {
            break;
        }
    }
    // Checks whether there is a need to switch two join branches.
    if (rewritten && needToSwitch) {
        Mutable<ILogicalOperator> leftBranch = op.getInputs().get(0);
        Mutable<ILogicalOperator> rightBranch = op.getInputs().get(1);
        op.getInputs().set(0, rightBranch);
        op.getInputs().set(1, leftBranch);
    }
    AbstractBinaryJoinOperator returnOp = op;
    // After rewriting, the original inner join should become an left outer join.
    if (rewritten) {
        returnOp = new LeftOuterJoinOperator(op.getCondition());
        returnOp.getInputs().addAll(op.getInputs());
        injectNullCheckVars(returnOp);
    }
    return returnOp;
}
Also used : ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) LeftOuterJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)

Example 25 with AbstractBinaryJoinOperator

use of org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator in project asterixdb by apache.

the class AqlPlusExpressionToPlanTranslator method visitJoinClause.

@Override
public Pair<ILogicalOperator, LogicalVariable> visitJoinClause(JoinClause jc, Mutable<ILogicalOperator> tupSource) throws CompilationException {
    Mutable<ILogicalOperator> opRef = tupSource;
    Pair<ILogicalOperator, LogicalVariable> leftSide = null;
    for (Clause c : jc.getLeftClauses()) {
        leftSide = c.accept(this, opRef);
        opRef = new MutableObject<ILogicalOperator>(leftSide.first);
    }
    opRef = tupSource;
    Pair<ILogicalOperator, LogicalVariable> rightSide = null;
    for (Clause c : jc.getRightClauses()) {
        rightSide = c.accept(this, opRef);
        opRef = new MutableObject<ILogicalOperator>(rightSide.first);
    }
    Pair<ILogicalExpression, Mutable<ILogicalOperator>> whereCond = langExprToAlgExpression(jc.getWhereExpr(), tupSource);
    AbstractBinaryJoinOperator join;
    switch(jc.getKind()) {
        case INNER:
            join = new InnerJoinOperator(new MutableObject<ILogicalExpression>(whereCond.first));
            break;
        case LEFT_OUTER:
            join = new LeftOuterJoinOperator(new MutableObject<ILogicalExpression>(whereCond.first));
            break;
        default:
            throw new CompilationException(ErrorCode.COMPILATION_AQLPLUS_NO_SUCH_JOIN_TYPE);
    }
    join.getInputs().add(new MutableObject<ILogicalOperator>(leftSide.first));
    join.getInputs().add(new MutableObject<ILogicalOperator>(rightSide.first));
    return new Pair<ILogicalOperator, LogicalVariable>(join, null);
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) CompilationException(org.apache.asterix.common.exceptions.CompilationException) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) LeftOuterJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator) InnerJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) MetaVariableClause(org.apache.asterix.lang.aql.clause.MetaVariableClause) JoinClause(org.apache.asterix.lang.aql.clause.JoinClause) Clause(org.apache.asterix.lang.common.base.Clause) MutableObject(org.apache.commons.lang3.mutable.MutableObject) Pair(org.apache.hyracks.algebricks.common.utils.Pair)

Aggregations

AbstractBinaryJoinOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)27 ILogicalOperator (org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)24 AbstractLogicalOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator)18 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)14 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)11 ArrayList (java.util.ArrayList)9 SelectOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator)9 Mutable (org.apache.commons.lang3.mutable.Mutable)7 MutableObject (org.apache.commons.lang3.mutable.MutableObject)5 InnerJoinOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator)5 Dataset (org.apache.asterix.metadata.entities.Dataset)4 ILogicalPlan (org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan)4 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)4 AggregateOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator)4 LeftOuterJoinOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.LeftOuterJoinOperator)4 HashSet (java.util.HashSet)3 AssignOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator)3 Clause (org.apache.asterix.lang.common.base.Clause)2 MetadataProvider (org.apache.asterix.metadata.declared.MetadataProvider)2 IAType (org.apache.asterix.om.types.IAType)2