Search in sources :

Example 1 with OrderOperator

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

the class EnforceOrderByAfterSubplan method rewritePost.

@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
    AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
    if (context.checkIfInDontApplySet(this, op1)) {
        return false;
    }
    List<Mutable<ILogicalOperator>> inputs = op1.getInputs();
    context.addToDontApplySet(this, op1);
    if (op1.getOperatorTag() == LogicalOperatorTag.ORDER || inputs == null) {
        /**
             * does not apply if
             * 1. there is yet-another order operator on-top-of the subplan, because the downstream order operator's ordering will be broken anyway
             * 2. the input operator(s) is null
             */
        return false;
    }
    boolean changed = false;
    for (int i = 0; i < inputs.size(); i++) {
        Mutable<ILogicalOperator> inputOpRef = inputs.get(i);
        AbstractLogicalOperator op = (AbstractLogicalOperator) inputOpRef.getValue();
        context.addToDontApplySet(this, op);
        if (op.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
            continue;
        }
        /**
             * check the order operators whose ordering is not broken before the subplan operator, and then
             * duplicate them on-top-of the subplan operator
             */
        boolean foundTarget = true;
        boolean orderSensitive = false;
        Mutable<ILogicalOperator> childRef = op.getInputs().get(0);
        AbstractLogicalOperator child = (AbstractLogicalOperator) childRef.getValue();
        while (child.getOperatorTag() != LogicalOperatorTag.ORDER) {
            context.addToDontApplySet(this, child);
            if (orderBreakingOps.contains(child.getOperatorTag())) {
                foundTarget = false;
                break;
            }
            if (child.getOperatorTag() == LogicalOperatorTag.GROUP) {
                foundTarget = false;
                break;
            }
            if (orderSensitiveOps.contains(child.getOperatorTag())) {
                orderSensitive = true;
            }
            List<Mutable<ILogicalOperator>> childInputs = child.getInputs();
            if (childInputs == null || childInputs.size() > 2 || childInputs.size() < 1) {
                foundTarget = false;
                break;
            } else {
                childRef = childInputs.get(0);
                child = (AbstractLogicalOperator) childRef.getValue();
            }
        }
        /** the target order-by operator has not been found. */
        if (!foundTarget) {
            return false;
        }
        /** copy the original order-by operator and insert on-top-of the subplan operator */
        context.addToDontApplySet(this, child);
        OrderOperator sourceOrderOp = (OrderOperator) child;
        for (Pair<IOrder, Mutable<ILogicalExpression>> expr : sourceOrderOp.getOrderExpressions()) {
            if (!expr.second.getValue().isFunctional()) {
                return false;
            }
        }
        List<Pair<IOrder, Mutable<ILogicalExpression>>> orderExprs = deepCopyOrderAndExpression(sourceOrderOp.getOrderExpressions());
        OrderOperator newOrderOp = new OrderOperator(orderExprs);
        context.addToDontApplySet(this, newOrderOp);
        inputs.set(i, new MutableObject<ILogicalOperator>(newOrderOp));
        newOrderOp.getInputs().add(inputOpRef);
        context.computeAndSetTypeEnvironmentForOperator(newOrderOp);
        if (!orderSensitive) {
            /** remove the original order-by */
            childRef.setValue(sourceOrderOp.getInputs().get(0).getValue());
        }
        changed = true;
    }
    return changed;
}
Also used : AbstractLogicalOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator) IOrder(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) OrderOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) Pair(org.apache.hyracks.algebricks.common.utils.Pair)

Example 2 with OrderOperator

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

the class PushLimitIntoOrderByRule method pushLimitIntoOrder.

/**
     * Generate new ORDER operator that uses TopKSort module and replaces the old ORDER operator.
     */
private boolean pushLimitIntoOrder(Mutable<ILogicalOperator> opRef, Mutable<ILogicalOperator> opRef2, IOptimizationContext context) throws AlgebricksException {
    PhysicalOptimizationConfig physicalOptimizationConfig = context.getPhysicalOptimizationConfig();
    LimitOperator limitOp = (LimitOperator) opRef.getValue();
    OrderOperator orderOp = (OrderOperator) opRef2.getValue();
    long topK = -1;
    // We don't push-down LIMIT into in-memory sort.
    if (orderOp.getPhysicalOperator().getOperatorTag() != PhysicalOperatorTag.STABLE_SORT) {
        return false;
    }
    // Get the LIMIT constant
    if (limitOp.getMaxObjects().getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
        // Currently, we support LIMIT with a constant value.
        topK = AccessMethodUtils.getInt64Constant(limitOp.getMaxObjects());
        // since the original external sort's performance might be better.
        if (topK > Integer.MAX_VALUE) {
            return false;
        }
        if (topK < 0) {
            topK = 0;
        }
    } else {
        return false;
    }
    // Final topK will be applied through LIMIT.
    if (limitOp.getOffset().getValue() != null) {
        if (limitOp.getOffset().getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
            long offset = AccessMethodUtils.getInt64Constant(limitOp.getOffset());
            if (offset < 0) {
                offset = 0;
            }
            // Check the overflow case.
            if (offset >= Integer.MAX_VALUE - topK) {
                return false;
            }
            topK += offset;
        } else {
            return false;
        }
    }
    // Create the new ORDER operator, set the topK value, and replace the current one.
    OrderOperator newOrderOp = new OrderOperator(orderOp.getOrderExpressions(), (int) topK);
    newOrderOp.setPhysicalOperator(new StableSortPOperator(physicalOptimizationConfig.getMaxFramesExternalSort(), newOrderOp.getTopK()));
    newOrderOp.getInputs().addAll(orderOp.getInputs());
    newOrderOp.setExecutionMode(orderOp.getExecutionMode());
    newOrderOp.recomputeSchema();
    newOrderOp.computeDeliveredPhysicalProperties(context);
    opRef2.setValue(newOrderOp);
    context.computeAndSetTypeEnvironmentForOperator(newOrderOp);
    context.addToDontApplySet(this, limitOp);
    return true;
}
Also used : LimitOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.LimitOperator) OrderOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator) PhysicalOptimizationConfig(org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig) StableSortPOperator(org.apache.hyracks.algebricks.core.algebra.operators.physical.StableSortPOperator)

Example 3 with OrderOperator

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

the class LogicalOperatorDeepCopyWithNewVariablesVisitor method visitOrderOperator.

@Override
public ILogicalOperator visitOrderOperator(OrderOperator op, ILogicalOperator arg) throws AlgebricksException {
    OrderOperator opCopy = new OrderOperator(deepCopyOrderExpressionReferencePairList(op.getOrderExpressions()));
    deepCopyInputsAnnotationsAndExecutionMode(op, arg, opCopy);
    return opCopy;
}
Also used : OrderOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator)

Example 4 with OrderOperator

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

the class InlineAllNtsInSubplanVisitor method wrapLimitInGroupBy.

private Pair<ILogicalOperator, LogicalVariable> wrapLimitInGroupBy(ILogicalOperator op, LogicalVariable recordVar, Set<LogicalVariable> inputLiveVars) throws AlgebricksException {
    GroupByOperator gbyOp = new GroupByOperator();
    List<Pair<LogicalVariable, LogicalVariable>> keyVarNewVarPairs = new ArrayList<>();
    for (LogicalVariable keyVar : correlatedKeyVars) {
        // This limits the visitor can only be applied to a nested logical
        // plan inside a Subplan operator,
        // where the keyVarsToEnforce forms a candidate key which can
        // uniquely identify a tuple out of the nested-tuple-source.
        LogicalVariable newVar = context.newVar();
        gbyOp.getGroupByList().add(new Pair<>(newVar, new MutableObject<>(new VariableReferenceExpression(keyVar))));
        keyVarNewVarPairs.add(new Pair<>(keyVar, newVar));
    }
    // Creates an aggregate operator doing LISTIFY, as the root of the
    // nested plan of the added group-by operator.
    List<LogicalVariable> aggVarList = new ArrayList<LogicalVariable>();
    List<Mutable<ILogicalExpression>> aggExprList = new ArrayList<Mutable<ILogicalExpression>>();
    LogicalVariable aggVar = context.newVar();
    List<Mutable<ILogicalExpression>> aggArgList = new ArrayList<>();
    aggVarList.add(aggVar);
    // Creates an aggregation function expression.
    aggArgList.add(new MutableObject<>(new VariableReferenceExpression(recordVar)));
    ILogicalExpression aggExpr = new AggregateFunctionCallExpression(FunctionUtil.getFunctionInfo(BuiltinFunctions.LISTIFY), false, aggArgList);
    aggExprList.add(new MutableObject<>(aggExpr));
    AggregateOperator aggOp = new AggregateOperator(aggVarList, aggExprList);
    // Adds the original limit operator as the input operator to the added
    // aggregate operator.
    aggOp.getInputs().add(new MutableObject<>(op));
    op.getInputs().clear();
    ILogicalOperator currentOp = op;
    if (!orderingExprs.isEmpty()) {
        OrderOperator orderOp = new OrderOperator(cloneOrderingExpression(orderingExprs));
        op.getInputs().add(new MutableObject<>(orderOp));
        currentOp = orderOp;
    }
    // Adds a nested tuple source operator as the input operator to the
    // limit operator.
    NestedTupleSourceOperator nts = new NestedTupleSourceOperator(new MutableObject<ILogicalOperator>(gbyOp));
    currentOp.getInputs().add(new MutableObject<>(nts));
    // Sets the root of the added nested plan to the aggregate operator.
    ILogicalPlan nestedPlan = new ALogicalPlanImpl();
    nestedPlan.getRoots().add(new MutableObject<>(aggOp));
    // Sets the nested plan for the added group-by operator.
    gbyOp.getNestedPlans().add(nestedPlan);
    // Updates variable mapping for ancestor operators.
    for (Pair<LogicalVariable, LogicalVariable> keyVarNewVar : keyVarNewVarPairs) {
        updateInputToOutputVarMapping(keyVarNewVar.first, keyVarNewVar.second, false);
    }
    return new Pair<>(gbyOp, aggVar);
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) AggregateFunctionCallExpression(org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression) NestedTupleSourceOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.NestedTupleSourceOperator) GroupByOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator) ILogicalOperator(org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator) ArrayList(java.util.ArrayList) OrderOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) ALogicalPlanImpl(org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) AggregateOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator) RunningAggregateOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.RunningAggregateOperator) ILogicalPlan(org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan) Pair(org.apache.hyracks.algebricks.common.utils.Pair) MutableObject(org.apache.commons.lang3.mutable.MutableObject)

Example 5 with OrderOperator

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

the class InlineLeftNtsInSubplanJoinFlatteningVisitor method visitOrderOperator.

@Override
public ILogicalOperator visitOrderOperator(OrderOperator op, Void arg) throws AlgebricksException {
    boolean underJoin = hasJoinAncestor;
    visitSingleInputOperator(op);
    if (!rewritten || !underJoin) {
        return op;
    }
    // Adjust the ordering if its input operator pipeline has been rewritten.
    List<Pair<IOrder, Mutable<ILogicalExpression>>> orderExprList = new ArrayList<>();
    // Adds keyVars to the prefix of sorting columns.
    for (LogicalVariable liveVar : liveVarsFromSubplanInput) {
        orderExprList.add(new Pair<IOrder, Mutable<ILogicalExpression>>(OrderOperator.ASC_ORDER, new MutableObject<ILogicalExpression>(new VariableReferenceExpression(liveVar))));
    }
    orderExprList.addAll(op.getOrderExpressions());
    // Creates an order operator with the new expression list.
    OrderOperator orderOp = new OrderOperator(orderExprList);
    orderOp.getInputs().addAll(op.getInputs());
    context.computeAndSetTypeEnvironmentForOperator(orderOp);
    return orderOp;
}
Also used : LogicalVariable(org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable) Mutable(org.apache.commons.lang3.mutable.Mutable) ILogicalExpression(org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression) IOrder(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder) VariableReferenceExpression(org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression) ArrayList(java.util.ArrayList) OrderOperator(org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator) Pair(org.apache.hyracks.algebricks.common.utils.Pair) MutableObject(org.apache.commons.lang3.mutable.MutableObject)

Aggregations

OrderOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator)17 Mutable (org.apache.commons.lang3.mutable.Mutable)14 ILogicalExpression (org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression)12 VariableReferenceExpression (org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression)11 ILogicalOperator (org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator)10 LogicalVariable (org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable)10 IOrder (org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator.IOrder)9 ArrayList (java.util.ArrayList)8 MutableObject (org.apache.commons.lang3.mutable.MutableObject)8 Pair (org.apache.hyracks.algebricks.common.utils.Pair)8 ScalarFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression)4 AbstractLogicalOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator)4 ILogicalPlan (org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan)3 AbstractFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression)3 GroupByOperator (org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator)3 HashSet (java.util.HashSet)2 List (java.util.List)2 IAObject (org.apache.asterix.om.base.IAObject)2 AlgebricksException (org.apache.hyracks.algebricks.common.exceptions.AlgebricksException)2 AggregateFunctionCallExpression (org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression)2