>From <[email protected]>:
[email protected] has uploaded this change for review. (
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18788 )
Change subject: [ASTERIXDB-3496][COMP] Move Array related Unnest Operator
higher up in the tree.
......................................................................
[ASTERIXDB-3496][COMP] Move Array related Unnest Operator higher up in the tree.
Change-Id: Ief11655b5131e8fe472f2743289da49c53b86fae
---
A
asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
M
hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
M
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
4 files changed, 194 insertions(+), 8 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb
refs/changes/88/18788/1
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
index 4a97acb..17488c9 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
@@ -20,6 +20,7 @@
package org.apache.asterix.optimizer.rules.cbo;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
@@ -57,6 +58,7 @@
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import
org.apache.hyracks.algebricks.core.algebra.operators.logical.UnnestOperator;
import
org.apache.hyracks.algebricks.core.algebra.operators.logical.visitors.VariableUtilities;
import org.apache.hyracks.algebricks.core.algebra.plan.ALogicalPlanImpl;
import
org.apache.hyracks.algebricks.core.algebra.prettyprint.IPlanPrettyPrinter;
@@ -92,6 +94,13 @@
// The OrderBy operator at root of the query tree (if exists)
private ILogicalOperator rootOrderByOp;
+ //first is Operator whose input has to be changed
+ // second input number that has to be changed
+ // third Assign Operator at the top
+ // fourth Unnest operator at the bottom
+ private List<Quadruple<ILogicalOperator, Integer, ILogicalOperator,
ILogicalOperator>> parentAssignUnnestOps =
+ new ArrayList<>(); // assign on top of Unnest. Save the parent of
the assign op
+ private ILogicalOperator returnOp;
private List<LogicalVariable> resultAndJoinVars = new ArrayList();
@@ -245,14 +254,19 @@
printPlan(pp, (AbstractLogicalOperator) newJoinOps.get(0), "New
Whole Plan after buildNewTree 2");
printPlan(pp, (AbstractLogicalOperator) root, "New Whole Plan
after buildNewTree");
+ opRef.setValue(root);
+ context.computeAndSetTypeEnvironmentForOperator(root);
+ String viewOutPlan2 = new ALogicalPlanImpl(opRef).toString();
//useful when debugging
+ root = moveUnnestOps(root);
+
// this will be the new root
opRef.setValue(root);
-
- if (LOGGER.isTraceEnabled()) {
- String viewOutPlan = new ALogicalPlanImpl(opRef).toString();
//useful when debugging
- LOGGER.trace("viewOutPlan");
- LOGGER.trace(viewOutPlan);
- }
+ context.computeAndSetTypeEnvironmentForOperator(root);
+ //if (LOGGER.isTraceEnabled()) {
+ String viewOutPlan = new ALogicalPlanImpl(opRef).toString();
//useful when debugging
+ LOGGER.trace("viewOutPlan");
+ LOGGER.trace(viewOutPlan);
+ //}
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("---------------------------- Printing Leaf
Inputs");
@@ -271,10 +285,111 @@
} else {
buildNewTree(cheapestPlanNode);
}
- context.computeAndSetTypeEnvironmentForOperator(op);
+ //context.computeAndSetTypeEnvironmentForOperator(op);
return true;
}
+ private ILogicalOperator moveUnnestOps(ILogicalOperator root) throws
AlgebricksException {
+ findUnnestOps(root);
+ //removeUnnestOps();
+
+ for (int i = 0; i < parentAssignUnnestOps.size(); i++) {
+ ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+ int inputNo = parentAssignUnnestOps.get(i).getSecond();
+ AssignOperator aOp = (AssignOperator)
parentAssignUnnestOps.get(i).getThird();
+ if (aOp.getVariables().size() == 1) { // handle only this case for
now.
+ LogicalVariable var = aOp.getVariables().get(0);
+ returnOp = null;
+ findOperatorWithThisVar(var, newJoinOps.get(0));
+ if (returnOp == null) {
+ // Now remove this UnnestOp from its original place
+ removeUnnestOp2(i);
+
parentAssignUnnestOps.get(i).getFourth().getInputs().get(0).setValue(root);
+ root = aOp;
+ }
+ /*else {
+ ILogicalOperator saveInput =
op.getInputs().get(inputNo).getValue(); // but do we know if this is the right
input??
+
op.getInputs().get(0).getValue().getInputs().get(inputNo).setValue(aOp);
+
parentAssignUnnestOps.get(i).getFourth().getInputs().get(0).setValue(saveInput);
+ }*/
+ }
+ }
+ return root;
+ }
+
+ private void findOperatorWithThisVar(LogicalVariable var, ILogicalOperator
op) throws AlgebricksException {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.EMPTYTUPLESOURCE)) {
+ return;
+ }
+ Collection<LogicalVariable> vars = new ArrayList<>();
+ //skip the original
+ VariableUtilities.getUsedVariables(op, vars);
+ if (vars.contains(var)) {
+ returnOp = op;
+ return;
+ }
+ for (int i = 0; i < op.getInputs().size(); i++) {
+ findOperatorWithThisVar(var, op.getInputs().get(i).getValue());
+ }
+ }
+
+ private void removeUnnestOp(int n) {
+ for (int i = n; i <= n; i++) {
+ ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+ int inputNo = parentAssignUnnestOps.get(i).getSecond();
+ AssignOperator aOp = (AssignOperator)
(lOp.getInputs().get(inputNo).getValue());
+ ILogicalOperator unnestOp = aOp.getInputs().get(0).getValue();
+
lOp.getInputs().get(inputNo).setValue(unnestOp.getInputs().get(0).getValue());
+ // This bypasses the AssignOp and the UnnestOp. We will hopefully
find a better place for this AssignUnnest Pair.
+ }
+ }
+
+ private void removeUnnestOp2(int i) {
+
+ ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+ int inputNo = parentAssignUnnestOps.get(i).getSecond();
+ AssignOperator aOp = (AssignOperator)
parentAssignUnnestOps.get(i).getThird();
+ UnnestOperator unnestOp = (UnnestOperator)
parentAssignUnnestOps.get(i).getFourth();
+
lOp.getInputs().get(inputNo).setValue(unnestOp.getInputs().get(0).getValue());
+
+ }
+
+ private void removeUnnestOps() {
+ for (int i = 0; i < parentAssignUnnestOps.size(); i++) {
+ ILogicalOperator lOp = parentAssignUnnestOps.get(i).getFirst();
+ int inputNo = parentAssignUnnestOps.get(i).getSecond();
+ AssignOperator aOp = (AssignOperator)
(lOp.getInputs().get(inputNo).getValue());
+ ILogicalOperator unnestOp = aOp.getInputs().get(0).getValue();
+
lOp.getInputs().get(inputNo).setValue(unnestOp.getInputs().get(0).getValue());
+ // This bypasses the AssignOp and the UnnestOp. We will hopefully
find a better place for this AssignUnnest Pair.
+ }
+ }
+
+ private void findUnnestOps(ILogicalOperator op) {
+ for (int i = 0; i < op.getInputs().size(); i++) {
+ ILogicalOperator p = op.getInputs().get(i).getValue();
+ if (p.getOperatorTag() == LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ return;
+ }
+ if (p.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
+ // Tackling only one ASSIGN and UNNEST FOR NOW
+ if (p.getInputs().get(0).getValue().getOperatorTag() ==
LogicalOperatorTag.ASSIGN) {
+ return;
+ }
+ if (p.getInputs().get(0).getValue().getOperatorTag() ==
LogicalOperatorTag.UNNEST) {
+ UnnestOperator unnestOp = (UnnestOperator)
p.getInputs().get(0).getValue();
+ ILogicalExpression foo =
unnestOp.getExpressionRef().getValue();
+ LogicalExpressionTag tag = foo.getExpressionTag();
+ //Expression expr = (Expression)
unnestOp.getExpressionRef();
+ if (unnestOp.getArray()) {
+ parentAssignUnnestOps.add(new Quadruple(op, i, p,
p.getInputs().get(0).getValue()));
+ }
+ }
+ }
+ findUnnestOps(p);
+ }
+ }
+
private void collectJoinConditionsVariables() {
for (JoinOperator jOp : allJoinOps) {
AbstractBinaryJoinOperator joinOp = jOp.getAbstractJoinOp();
@@ -1042,4 +1157,4 @@
}
return true;
}
-}
\ No newline at end of file
+}
diff --git
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
index 302d4e0..0d58589 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/translator/SqlppExpressionToPlanTranslator.java
@@ -330,6 +330,9 @@
} else {
unnestOp = new UnnestOperator(fromVar, new
MutableObject<>(pUnnestExpr.first));
}
+ if (fromExpr.getKind() == Kind.FIELD_ACCESSOR_EXPRESSION) {
+ unnestOp.setArray(true);
+ }
ExternalSubpathAnnotation hint = ((AbstractExpression)
fromExpr).findHint(ExternalSubpathAnnotation.class);
if (hint != null) {
unnestOp.getAnnotations().put(SUBPATH, hint.getSubPath());
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
new file mode 100644
index 0000000..5b622c2
--- /dev/null
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
@@ -0,0 +1,50 @@
+-- DISTRIBUTE_RESULT |UNPARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
+ -- STREAM_LIMIT |UNPARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$193(DESC), $$o_entry_d(ASC) ]
|PARTITIONED|
+ -- STREAM_LIMIT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [topK: 100] [$$193(DESC), $$o_entry_d(ASC)]
|PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- SORT_GROUP_BY[$$199, $$200, $$201, $$202,
$$203, $$204, $$205] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- HASH_PARTITION_EXCHANGE [$$199, $$200,
$$201, $$202, $$203, $$204, $$205] |PARTITIONED|
+ -- SORT_GROUP_BY[$$175, $$183, $$184, $$185,
$$179, $$180, $$181] |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- UNNEST |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE
|PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$188,
$$183, $$184][$$185, $$189, $$190] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE
[$$188, $$183, $$184] |PARTITIONED|
+ -- STREAM_PROJECT
|PARTITIONED|
+ -- ASSIGN
|PARTITIONED|
+ -- STREAM_PROJECT
|PARTITIONED|
+ --
ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ --
DATASOURCE_SCAN (test.orders) |PARTITIONED|
+ --
ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ --
EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE
[$$185, $$189, $$190] |PARTITIONED|
+ -- STREAM_PROJECT
|PARTITIONED|
+ -- ASSIGN
|PARTITIONED|
+ -- STREAM_PROJECT
|PARTITIONED|
+ --
ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ --
DATASOURCE_SCAN (test.customer) |PARTITIONED|
+ --
ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ --
EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
index face56e..d6252a8 100644
---
a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
+++
b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/operators/logical/UnnestOperator.java
@@ -28,6 +28,7 @@
import
org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalOperatorVisitor;
public class UnnestOperator extends AbstractUnnestNonMapOperator {
+ private boolean array = false;
public UnnestOperator(LogicalVariable variable,
Mutable<ILogicalExpression> expression) {
super(variable, expression);
@@ -58,4 +59,12 @@
public LogicalOperatorTag getOperatorTag() {
return LogicalOperatorTag.UNNEST;
}
+
+ public void setArray(boolean array) {
+ this.array = array;
+ }
+
+ public boolean getArray() {
+ return array;
+ }
}
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18788
To unsubscribe, or for help writing mail filters, visit
https://asterix-gerrit.ics.uci.edu/settings
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: Ief11655b5131e8fe472f2743289da49c53b86fae
Gerrit-Change-Number: 18788
Gerrit-PatchSet: 1
Gerrit-Owner: [email protected]
Gerrit-MessageType: newchange