Search in sources :

Example 6 with SelectOperator

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

the class LogicalOperatorDeepCopyWithNewVariablesVisitor method visitSelectOperator.

@Override
public ILogicalOperator visitSelectOperator(SelectOperator op, ILogicalOperator arg) throws AlgebricksException {
    SelectOperator opCopy = new SelectOperator(exprDeepCopyVisitor.deepCopyExpressionReference(op.getCondition()), op.getRetainMissing(), deepCopyVariable(op.getMissingPlaceholderVariable()));
    deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy);
    return opCopy;
}
Also used : SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator)

Example 7 with SelectOperator

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

the class RTreeAccessMethod 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 {
    // 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);
    }
    // TODO: We can probably do something smarter here based on selectivity or MBR area.
    ILogicalOperator primaryIndexUnnestOp = createSecondaryToPrimaryPlan(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);
    }
    indexSubTree.getDataSourceRef().setValue(primaryIndexUnnestOp);
    // Change join into a select with the same condition.
    AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) joinRef.getValue();
    SelectOperator topSelect = new SelectOperator(joinOp.getCondition(), 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);
    return true;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) 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 8 with SelectOperator

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

the class InvertedIndexAccessMethod 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 {
    // Figure out 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;
    }
    IOptimizableFuncExpr optFuncExpr = AccessMethodUtils.chooseFirstOptFuncExpr(chosenIndex, analysisCtx);
    // if the dataset of index subtree and the dataset of first argument's subtree is the same
    if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CONTAINS && optFuncExpr.getOperatorSubTree(0).getDataset() != null && !optFuncExpr.getOperatorSubTree(0).getDataset().getDatasetName().equals(indexSubTree.getDataset().getDatasetName())) {
        return false;
    }
    //if LOJ, reset null place holder variable
    LogicalVariable newNullPlaceHolderVar = null;
    if (isLeftOuterJoin && hasGroupBy) {
        //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);
        //reset the null place holder variable
        AccessMethodUtils.resetLOJNullPlaceholderVariableInGroupByOp(analysisCtx, newNullPlaceHolderVar, context);
    }
    AbstractBinaryJoinOperator join = (AbstractBinaryJoinOperator) joinRef.getValue();
    // Remember the original probe subtree, and its primary-key variables,
    // so we can later retrieve the missing attributes via an equi join.
    List<LogicalVariable> originalSubTreePKs = new ArrayList<>();
    // Remember the primary-keys of the new probe subtree for the top-level equi join.
    List<LogicalVariable> surrogateSubTreePKs = new ArrayList<>();
    // Copy probe subtree, replacing their variables with new ones. We will use the original variables
    // to stitch together a top-level equi join.
    Mutable<ILogicalOperator> originalProbeSubTreeRootRef = copyAndReinitProbeSubTree(probeSubTree, join.getCondition().getValue(), optFuncExpr, originalSubTreePKs, surrogateSubTreePKs, context);
    // Remember original live variables from the index sub tree.
    List<LogicalVariable> indexSubTreeLiveVars = new ArrayList<>();
    VariableUtilities.getLiveVariables(indexSubTree.getRoot(), indexSubTreeLiveVars);
    // Clone the original join condition because we may have to modify it (and we also need the original).
    ILogicalExpression joinCond = join.getCondition().getValue().cloneExpression();
    // Create "panic" (non indexed) nested-loop join path if necessary.
    Mutable<ILogicalOperator> panicJoinRef = null;
    Map<LogicalVariable, LogicalVariable> panicVarMap = null;
    if (optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CHECK || optFuncExpr.getFuncExpr().getFunctionIdentifier() == BuiltinFunctions.EDIT_DISTANCE_CONTAINS) {
        panicJoinRef = new MutableObject<>(joinRef.getValue());
        panicVarMap = new HashMap<>();
        Mutable<ILogicalOperator> newProbeRootRef = createPanicNestedLoopJoinPlan(panicJoinRef, indexSubTree, probeSubTree, optFuncExpr, chosenIndex, panicVarMap, context);
        probeSubTree.getRootRef().setValue(newProbeRootRef.getValue());
        probeSubTree.setRoot(newProbeRootRef.getValue());
    }
    // Create regular indexed-nested loop join path.
    ILogicalOperator indexPlanRootOp = createSecondaryToPrimaryPlan(null, indexSubTree, probeSubTree, chosenIndex, analysisCtx, true, isLeftOuterJoin, true, context);
    indexSubTree.getDataSourceRef().setValue(indexPlanRootOp);
    // Change join into a select with the same condition.
    SelectOperator topSelect = new SelectOperator(new MutableObject<ILogicalExpression>(joinCond), isLeftOuterJoin, newNullPlaceHolderVar);
    topSelect.getInputs().add(indexSubTree.getRootRef());
    topSelect.setExecutionMode(ExecutionMode.LOCAL);
    context.computeAndSetTypeEnvironmentForOperator(topSelect);
    ILogicalOperator topOp = topSelect;
    // Hook up the indexed-nested loop join path with the "panic" (non indexed) nested-loop join path by putting a union all on top.
    if (panicJoinRef != null) {
        LogicalVariable inputSearchVar = getInputSearchVar(optFuncExpr, indexSubTree);
        indexSubTreeLiveVars.addAll(originalSubTreePKs);
        indexSubTreeLiveVars.add(inputSearchVar);
        List<LogicalVariable> panicPlanLiveVars = new ArrayList<>();
        VariableUtilities.getLiveVariables(panicJoinRef.getValue(), panicPlanLiveVars);
        // Create variable mapping for union all operator.
        List<Triple<LogicalVariable, LogicalVariable, LogicalVariable>> varMap = new ArrayList<>();
        for (int i = 0; i < indexSubTreeLiveVars.size(); i++) {
            LogicalVariable indexSubTreeVar = indexSubTreeLiveVars.get(i);
            LogicalVariable panicPlanVar = panicVarMap.get(indexSubTreeVar);
            if (panicPlanVar == null) {
                panicPlanVar = indexSubTreeVar;
            }
            varMap.add(new Triple<LogicalVariable, LogicalVariable, LogicalVariable>(indexSubTreeVar, panicPlanVar, indexSubTreeVar));
        }
        UnionAllOperator unionAllOp = new UnionAllOperator(varMap);
        unionAllOp.getInputs().add(new MutableObject<ILogicalOperator>(topOp));
        unionAllOp.getInputs().add(panicJoinRef);
        unionAllOp.setExecutionMode(ExecutionMode.PARTITIONED);
        context.computeAndSetTypeEnvironmentForOperator(unionAllOp);
        topOp = unionAllOp;
    }
    // Place a top-level equi-join on top to retrieve the missing variables from the original probe subtree.
    // The inner (build) branch of the join is the subtree with the data scan, since the result of the similarity join could potentially be big.
    // This choice may not always be the most efficient, but it seems more robust than the alternative.
    Mutable<ILogicalExpression> eqJoinConditionRef = createPrimaryKeysEqJoinCondition(originalSubTreePKs, surrogateSubTreePKs);
    InnerJoinOperator topEqJoin = new InnerJoinOperator(eqJoinConditionRef, originalProbeSubTreeRootRef, new MutableObject<ILogicalOperator>(topOp));
    topEqJoin.setExecutionMode(ExecutionMode.PARTITIONED);
    joinRef.setValue(topEqJoin);
    context.computeAndSetTypeEnvironmentForOperator(topEqJoin);
    return true;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) Dataset(org.apache.asterix.metadata.entities.Dataset) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) InnerJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.InnerJoinOperator) AbstractBinaryJoinOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator) Triple(org.apache.hyracks.algebricks.common.utils.Triple) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator) UnionAllOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.UnionAllOperator)

Example 9 with SelectOperator

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

the class InvertedIndexAccessMethod method createIsFilterableSelectOps.

private void createIsFilterableSelectOps(ILogicalOperator inputOp, LogicalVariable inputSearchVar, IAType inputSearchVarType, IOptimizableFuncExpr optFuncExpr, Index chosenIndex, IOptimizationContext context, Mutable<ILogicalOperator> isFilterableSelectOpRef, Mutable<ILogicalOperator> isNotFilterableSelectOpRef) throws AlgebricksException {
    // Create select operator for removing tuples that are not filterable.
    // First determine the proper filter function and args based on the type of the input search var.
    ILogicalExpression isFilterableExpr = null;
    switch(inputSearchVarType.getTypeTag()) {
        case STRING:
            {
                List<Mutable<ILogicalExpression>> isFilterableArgs = new ArrayList<Mutable<ILogicalExpression>>(4);
                isFilterableArgs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputSearchVar)));
                // Since we are optimizing a join, the similarity threshold should be the only constant in the optimizable function expression.
                isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantExpr(0)));
                isFilterableArgs.add(new MutableObject<ILogicalExpression>(AccessMethodUtils.createInt32Constant(chosenIndex.getGramLength())));
                boolean usePrePost = optFuncExpr.containsPartialField() ? false : true;
                isFilterableArgs.add(new MutableObject<ILogicalExpression>(AccessMethodUtils.createBooleanConstant(usePrePost)));
                isFilterableExpr = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.EDIT_DISTANCE_STRING_IS_FILTERABLE), isFilterableArgs);
                break;
            }
        case MULTISET:
        case ARRAY:
            List<Mutable<ILogicalExpression>> isFilterableArgs = new ArrayList<Mutable<ILogicalExpression>>(2);
            isFilterableArgs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(inputSearchVar)));
            // Since we are optimizing a join, the similarity threshold should be the only constant in the optimizable function expression.
            isFilterableArgs.add(new MutableObject<ILogicalExpression>(optFuncExpr.getConstantExpr(0)));
            isFilterableExpr = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.EDIT_DISTANCE_LIST_IS_FILTERABLE), isFilterableArgs);
            break;
        default:
            throw CompilationException.create(ErrorCode.NO_SUPPORTED_TYPE);
    }
    SelectOperator isFilterableSelectOp = new SelectOperator(new MutableObject<ILogicalExpression>(isFilterableExpr), false, null);
    isFilterableSelectOp.getInputs().add(new MutableObject<ILogicalOperator>(inputOp));
    isFilterableSelectOp.setExecutionMode(ExecutionMode.LOCAL);
    context.computeAndSetTypeEnvironmentForOperator(isFilterableSelectOp);
    // Select operator for removing tuples that are filterable.
    List<Mutable<ILogicalExpression>> isNotFilterableArgs = new ArrayList<Mutable<ILogicalExpression>>();
    isNotFilterableArgs.add(new MutableObject<ILogicalExpression>(isFilterableExpr));
    ILogicalExpression isNotFilterableExpr = new ScalarFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.NOT), isNotFilterableArgs);
    SelectOperator isNotFilterableSelectOp = new SelectOperator(new MutableObject<ILogicalExpression>(isNotFilterableExpr), false, null);
    isNotFilterableSelectOp.getInputs().add(new MutableObject<ILogicalOperator>(inputOp));
    isNotFilterableSelectOp.setExecutionMode(ExecutionMode.LOCAL);
    context.computeAndSetTypeEnvironmentForOperator(isNotFilterableSelectOp);
    isFilterableSelectOpRef.setValue(isFilterableSelectOp);
    isNotFilterableSelectOpRef.setValue(isNotFilterableSelectOp);
}
Also used : ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) List(java.util.List) ArrayList(java.util.ArrayList) MutableObject(org.apache.commons.lang3.mutable.MutableObject) ScalarFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)

Example 10 with SelectOperator

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

the class IntroduceSelectAccessMethodRule method checkAndApplyTheSelectTransformation.

/**
     * Recursively traverse the given plan and check whether a SELECT operator exists.
     * If one is found, maintain the path from the root to SELECT operator and
     * optimize the path from the SELECT operator to the EMPTY_TUPLE_SOURCE operator
     * if it is not already optimized.
     */
protected boolean checkAndApplyTheSelectTransformation(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
    AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
    boolean selectFoundAndOptimizationApplied;
    boolean isSelectOp = false;
    Mutable<ILogicalOperator> selectRefFromThisOp = null;
    SelectOperator selectOpFromThisOp = null;
    // Check the current operator pattern to see whether it is a JOIN or not.
    if (op.getOperatorTag() == LogicalOperatorTag.SELECT) {
        selectRef = opRef;
        selectOp = (SelectOperator) op;
        selectRefFromThisOp = opRef;
        selectOpFromThisOp = (SelectOperator) op;
        isSelectOp = true;
    } else {
        // This is not a SELECT operator. Remember this operator.
        afterSelectRefs.add(opRef);
    }
    // to make sure an earlier select in the path is optimized first.
    for (Mutable<ILogicalOperator> inputOpRef : op.getInputs()) {
        selectFoundAndOptimizationApplied = checkAndApplyTheSelectTransformation(inputOpRef, context);
        if (selectFoundAndOptimizationApplied) {
            return true;
        }
    }
    // Traverse the plan until we find a SELECT operator.
    if (isSelectOp) {
        // Restore the information from this operator since it might have been be set to null
        // if there are other select operators in the earlier path.
        selectRef = selectRefFromThisOp;
        selectOp = selectOpFromThisOp;
        // Decides the plan transformation check needs to be continued.
        // This variable is needed since we can't just return false
        // in order to keep this operator in the afterSelectRefs list.
        boolean continueCheck = true;
        // Already checked this SELECT operator? If not, this operator may be optimized.
        if (context.checkIfInDontApplySet(this, selectOp)) {
            continueCheck = false;
        }
        // For each access method, contains the information about
        // whether an available index can be applicable or not.
        Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = null;
        if (continueCheck) {
            analyzedAMs = new TreeMap<>();
        }
        // the given plan is truly optimizable or not.
        if (continueCheck && !checkSelectOpConditionAndInitSubTree(context)) {
            continueCheck = false;
        }
        // Check whether the function in the SELECT operator can be truly transformed.
        if (continueCheck && !analyzeSelectOrJoinOpConditionAndUpdateAnalyzedAM(selectCond, subTree.getAssignsAndUnnests(), analyzedAMs, context, typeEnvironment)) {
            continueCheck = false;
        }
        // This will be used to find an applicable index on the dataset.
        if (continueCheck && !subTree.setDatasetAndTypeMetadata((MetadataProvider) context.getMetadataProvider())) {
            continueCheck = false;
        }
        if (continueCheck) {
            // Map variables to the applicable indexes and find the field name and type.
            // Then find the applicable indexes for the variables used in the SELECT condition.
            fillSubTreeIndexExprs(subTree, analyzedAMs, context);
            // Prune the access methods based on the function expression and access methods.
            pruneIndexCandidates(analyzedAMs, context, typeEnvironment);
            // Choose all indexes that will be applied.
            List<Pair<IAccessMethod, Index>> chosenIndexes = chooseAllIndexes(analyzedAMs);
            if (chosenIndexes == null || chosenIndexes.isEmpty()) {
                // We can't apply any index for this SELECT operator
                context.addToDontApplySet(this, selectRef.getValue());
                return false;
            }
            // Apply plan transformation using chosen index.
            boolean res = intersectAllSecondaryIndexes(chosenIndexes, analyzedAMs, context);
            context.addToDontApplySet(this, selectOp);
            if (res) {
                OperatorPropertiesUtil.typeOpRec(opRef, context);
                return res;
            }
        }
        selectRef = null;
        selectOp = null;
        afterSelectRefs.add(opRef);
    }
    // Clean the path after SELECT operator by removing the current operator in the list.
    afterSelectRefs.remove(opRef);
    return false;
}
Also used : SelectOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator) AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) Pair(org.apache.hyracks.algebricks.common.utils.Pair)

Aggregations

SelectOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator)36 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)27 ILogicalOperator (org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)23 AbstractLogicalOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator)19 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)17 Mutable (org.apache.commons.lang3.mutable.Mutable)15 MutableObject (org.apache.commons.lang3.mutable.MutableObject)11 ArrayList (java.util.ArrayList)10 ScalarFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)10 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)10 AbstractBinaryJoinOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator)9 Pair (org.apache.hyracks.algebricks.common.utils.Pair)8 AssignOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator)7 HashSet (java.util.HashSet)6 AbstractFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression)6 GbyVariableExpressionPair (org.apache.asterix.lang.common.expression.GbyVariableExpressionPair)5 ILogicalPlan (org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan)5 AggregateOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator)5 NestedTupleSourceOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator)5 SubplanOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator)5