use of org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator in project asterixdb by apache.
the class ExtractGroupByDecorVariablesRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
ILogicalOperator op = opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
GroupByOperator groupByOperator = (GroupByOperator) op;
List<Pair<LogicalVariable, Mutable<ILogicalExpression>>> decorList = groupByOperator.getDecorList();
// Returns immediately if there is no decoration entry.
if (groupByOperator.getDecorList() == null || groupByOperator.getDecorList().isEmpty()) {
return false;
}
// Goes over the decoration list and performs the rewrite.
boolean changed = false;
List<LogicalVariable> vars = new ArrayList<>();
List<Mutable<ILogicalExpression>> exprs = new ArrayList<>();
for (Pair<LogicalVariable, Mutable<ILogicalExpression>> decorVarExpr : decorList) {
Mutable<ILogicalExpression> exprRef = decorVarExpr.second;
ILogicalExpression expr = exprRef.getValue();
if (expr == null || expr.getExpressionTag() == LogicalExpressionTag.VARIABLE) {
continue;
}
// Rewrites the decoration entry if the decoration expression is not a variable reference expression.
changed = true;
LogicalVariable newVar = context.newVar();
vars.add(newVar);
exprs.add(exprRef);
// Normalizes the decor entry -- expression be a variable reference
decorVarExpr.second = new MutableObject<>(new VariableReferenceExpression(newVar));
}
if (!changed) {
return false;
}
// Injects an assign operator to evaluate the decoration expression.
AssignOperator assignOperator = new AssignOperator(vars, exprs);
assignOperator.getInputs().addAll(op.getInputs());
op.getInputs().set(0, new MutableObject<>(assignOperator));
return changed;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator in project asterixdb by apache.
the class AbstractIntroduceGroupByCombinerRule method tryToPushRoot.
private boolean tryToPushRoot(Mutable<ILogicalOperator> root, GroupByOperator oldGbyOp, GroupByOperator newGbyOp, BookkeepingInfo bi, List<LogicalVariable> gbyVars, IOptimizationContext context, List<Mutable<ILogicalOperator>> toPushAccumulate, Set<SimilarAggregatesInfo> toReplaceSet) throws AlgebricksException {
AbstractLogicalOperator op1 = (AbstractLogicalOperator) root.getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
// Finds nested group-by if any.
AbstractLogicalOperator op3 = op2;
while (op3.getOperatorTag() != LogicalOperatorTag.GROUP && op3.getInputs().size() == 1) {
op3 = (AbstractLogicalOperator) op3.getInputs().get(0).getValue();
}
if (op3.getOperatorTag() != LogicalOperatorTag.GROUP) {
AggregateOperator initAgg = (AggregateOperator) op1;
Pair<Boolean, Mutable<ILogicalOperator>> pOpRef = tryToPushAgg(initAgg, newGbyOp, toReplaceSet, context);
if (!pOpRef.first) {
return false;
}
Mutable<ILogicalOperator> opRef = pOpRef.second;
if (opRef != null) {
toPushAccumulate.add(opRef);
}
bi.modifyGbyMap.put(oldGbyOp, gbyVars);
return true;
} else {
GroupByOperator nestedGby = (GroupByOperator) op3;
List<LogicalVariable> gbyVars2 = nestedGby.getGbyVarList();
Set<LogicalVariable> freeVars = new HashSet<>();
// Removes non-free variables defined in the nested plan.
OperatorPropertiesUtil.getFreeVariablesInSelfOrDesc(nestedGby, freeVars);
gbyVars2.retainAll(freeVars);
List<LogicalVariable> concatGbyVars = new ArrayList<LogicalVariable>(gbyVars);
concatGbyVars.addAll(gbyVars2);
for (ILogicalPlan p : nestedGby.getNestedPlans()) {
for (Mutable<ILogicalOperator> r2 : p.getRoots()) {
if (!tryToPushRoot(r2, nestedGby, newGbyOp, bi, concatGbyVars, context, toPushAccumulate, toReplaceSet)) {
return false;
}
}
}
/***
* Push the nested pipeline which provides the input to the nested group operator into newGbyOp (the combined gby op).
* The change is to fix asterixdb issue 782.
*/
// Finds the reference of the bottom-most operator in the pipeline that
// should not be pushed to the combiner group-by.
Mutable<ILogicalOperator> currentOpRef = new MutableObject<ILogicalOperator>(nestedGby);
Mutable<ILogicalOperator> bottomOpRef = findBottomOpRefStayInOldGby(currentOpRef);
// Adds the used variables in the pipeline from <code>currentOpRef</code> to <code>bottomOpRef</code>
// into the group-by keys for the introduced combiner group-by operator.
Set<LogicalVariable> usedVars = collectUsedFreeVariables(currentOpRef, bottomOpRef);
for (LogicalVariable usedVar : usedVars) {
if (!concatGbyVars.contains(usedVar)) {
concatGbyVars.add(usedVar);
}
}
// Retains the nested pipeline above the identified operator in the old group-by operator.
// Pushes the nested pipeline under the select operator into the new group-by operator.
Mutable<ILogicalOperator> oldNtsRef = findNtsRef(currentOpRef);
ILogicalOperator opToCombiner = bottomOpRef.getValue().getInputs().get(0).getValue();
if (opToCombiner.getOperatorTag() == LogicalOperatorTag.NESTEDTUPLESOURCE) {
// No pipeline other than the aggregate operator needs to push to combiner.
return true;
}
bottomOpRef.getValue().getInputs().set(0, new MutableObject<ILogicalOperator>(oldNtsRef.getValue()));
Mutable<ILogicalOperator> newGbyNestedOpRef = findNtsRef(toPushAccumulate.get(0));
NestedTupleSourceOperator newNts = (NestedTupleSourceOperator) newGbyNestedOpRef.getValue();
newGbyNestedOpRef.setValue(opToCombiner);
oldNtsRef.setValue(newNts);
return true;
}
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator in project asterixdb by apache.
the class FactorRedundantGroupAndDecorVarsRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
if (op.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
GroupByOperator gby = (GroupByOperator) op;
Map<LogicalVariable, LogicalVariable> varRhsToLhs = new HashMap<LogicalVariable, LogicalVariable>();
boolean gvChanged = factorRedundantRhsVars(gby.getGroupByList(), opRef, varRhsToLhs, context);
boolean dvChanged = factorRedundantRhsVars(gby.getDecorList(), opRef, varRhsToLhs, context);
return gvChanged || dvChanged;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator in project asterixdb by apache.
the class NestGroupByRule method rewritePost.
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) throws AlgebricksException {
AbstractLogicalOperator op1 = (AbstractLogicalOperator) opRef.getValue();
if (op1.getOperatorTag() != LogicalOperatorTag.SUBPLAN) {
return false;
}
SubplanOperator subplan = (SubplanOperator) op1;
if (subplan.getNestedPlans().size() != 1) {
return false;
}
ILogicalPlan p = subplan.getNestedPlans().get(0);
if (p.getRoots().size() != 1) {
return false;
}
Set<LogicalVariable> free = new HashSet<LogicalVariable>();
OperatorPropertiesUtil.getFreeVariablesInSubplans(subplan, free);
if (free.size() != 1) {
return false;
}
LogicalVariable fVar = null;
for (LogicalVariable v : free) {
fVar = v;
break;
}
AbstractLogicalOperator op2 = (AbstractLogicalOperator) op1.getInputs().get(0).getValue();
if (op2.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
GroupByOperator gby = (GroupByOperator) op2;
if (gby.getNestedPlans().size() != 1) {
return false;
}
ILogicalPlan p2 = gby.getNestedPlans().get(0);
if (p2.getRoots().size() != 1) {
return false;
}
Mutable<ILogicalOperator> r2 = p2.getRoots().get(0);
AbstractLogicalOperator opr2 = (AbstractLogicalOperator) r2.getValue();
if (opr2.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator aggOuter = (AggregateOperator) opr2;
int posInAggList = aggOuter.getVariables().indexOf(fVar);
if (posInAggList < 0) {
return false;
}
AbstractLogicalOperator outerAggSon = (AbstractLogicalOperator) aggOuter.getInputs().get(0).getValue();
if (outerAggSon.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
return false;
}
ILogicalExpression eAgg = aggOuter.getExpressions().get(posInAggList).getValue();
if (eAgg.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression listifyCall = (AbstractFunctionCallExpression) eAgg;
if (listifyCall.getFunctionIdentifier() != BuiltinFunctions.LISTIFY) {
return false;
}
ILogicalExpression argListify = listifyCall.getArguments().get(0).getValue();
if (argListify.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
Mutable<ILogicalOperator> r = p.getRoots().get(0);
AbstractLogicalOperator opInS = (AbstractLogicalOperator) r.getValue();
if (opInS.getOperatorTag() != LogicalOperatorTag.AGGREGATE) {
return false;
}
AggregateOperator aggInner = (AggregateOperator) opInS;
do {
opInS = (AbstractLogicalOperator) opInS.getInputs().get(0).getValue();
} while (opInS.getOperatorTag() == LogicalOperatorTag.ASSIGN);
if (opInS.getOperatorTag() != LogicalOperatorTag.GROUP) {
return false;
}
AbstractLogicalOperator unnestParent = opInS;
AbstractLogicalOperator opUnder = (AbstractLogicalOperator) opInS.getInputs().get(0).getValue();
// skip Assigns
while (opUnder.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
unnestParent = opUnder;
opUnder = (AbstractLogicalOperator) opUnder.getInputs().get(0).getValue();
}
if (opUnder.getOperatorTag() != LogicalOperatorTag.UNNEST) {
return false;
}
UnnestOperator unnest = (UnnestOperator) opUnder;
AbstractLogicalOperator unnestSon = (AbstractLogicalOperator) unnest.getInputs().get(0).getValue();
if (unnestSon.getOperatorTag() != LogicalOperatorTag.NESTEDTUPLESOURCE) {
return false;
}
NestedTupleSourceOperator innerNts = (NestedTupleSourceOperator) unnestSon;
ILogicalExpression eUnnest = unnest.getExpressionRef().getValue();
if (eUnnest.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
}
AbstractFunctionCallExpression uf = (AbstractFunctionCallExpression) eUnnest;
if (uf.getFunctionIdentifier() != BuiltinFunctions.SCAN_COLLECTION) {
return false;
}
ILogicalExpression scanArg = uf.getArguments().get(0).getValue();
if (scanArg.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
return false;
}
if (((VariableReferenceExpression) scanArg).getVariableReference() != fVar) {
return false;
}
LogicalVariable uVar = unnest.getVariable();
GroupByOperator innerGby = (GroupByOperator) opInS;
Set<LogicalVariable> freeInInnerGby = new HashSet<LogicalVariable>();
OperatorPropertiesUtil.getFreeVariablesInSubplans(innerGby, freeInInnerGby);
for (LogicalVariable v : freeInInnerGby) {
if (v != uVar) {
return false;
}
}
unnestParent.getInputs().get(0).setValue(innerNts);
LogicalVariable listifiedVar = ((VariableReferenceExpression) argListify).getVariableReference();
substInSubplan(aggInner, uVar, listifiedVar, context);
gby.getNestedPlans().add(p);
innerNts.getDataSourceReference().setValue(gby);
opRef.setValue(gby);
OperatorPropertiesUtil.typePlan(p, context);
OperatorPropertiesUtil.typePlan(p2, context);
context.computeAndSetTypeEnvironmentForOperator(gby);
return true;
}
use of org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator in project asterixdb by apache.
the class RequiredCapacityVisitorTest method testParallelGroupBy.
@Test
public void testParallelGroupBy() throws AlgebricksException {
IClusterCapacity clusterCapacity = new ClusterCapacity();
RequiredCapacityVisitor visitor = makeComputationCapacityVisitor(PARALLELISM, clusterCapacity);
// Constructs a parallel group-by query plan.
GroupByOperator globalGby = makeGroupByOperator(AbstractLogicalOperator.ExecutionMode.PARTITIONED);
ExchangeOperator exchange = new ExchangeOperator();
exchange.setPhysicalOperator(new HashPartitionExchangePOperator(Collections.emptyList(), null));
GroupByOperator localGby = makeGroupByOperator(AbstractLogicalOperator.ExecutionMode.LOCAL);
globalGby.getInputs().add(new MutableObject<>(exchange));
exchange.getInputs().add(new MutableObject<>(localGby));
// Verifies the calculated cluster capacity requirement for the test quer plan.
globalGby.accept(visitor, null);
Assert.assertTrue(clusterCapacity.getAggregatedCores() == PARALLELISM);
Assert.assertTrue(clusterCapacity.getAggregatedMemoryByteSize() == 2 * MEMORY_BUDGET * PARALLELISM + 2 * FRAME_SIZE * PARALLELISM * PARALLELISM);
}
Aggregations