[ASTERIXDB-3168][COMP] Refactor/share CBO code
Change-Id: I4c164cd517315f8ab9ae8df2baf06b4a72fedee5
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/17495
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Ali Alsuliman <ali.al.solaiman@gmail.com>
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/Cost.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/Cost.java
index 5dda277..45e6691 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/Cost.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/Cost.java
@@ -22,7 +22,7 @@
public class Cost implements ICost {
public static final double MAX_CARD = 1.0e200;
- protected static final int COST_EQ = 0;
+ private static final int COST_EQ = 0;
private final double cost;
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CostMethods.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CostMethods.java
index 5dafa54..887cc94 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CostMethods.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CostMethods.java
@@ -40,12 +40,12 @@
maxMemorySize = getMaxMemorySize();
}
- public long getBufferCacheSize() {
+ private long getBufferCacheSize() {
MetadataProvider metadataProvider = (MetadataProvider) optCtx.getMetadataProvider();
return metadataProvider.getStorageProperties().getBufferCacheSize();
}
- public long getBufferCachePageSize() {
+ private long getBufferCachePageSize() {
MetadataProvider metadataProvider = (MetadataProvider) optCtx.getMetadataProvider();
return metadataProvider.getStorageProperties().getBufferCachePageSize();
}
@@ -63,7 +63,11 @@
return new Cost(jn.computeJoinCardinality());
}
- public Cost costIndexScan(JoinNode jn) {
+ public Cost costIndexScan(JoinNode jn, double indexSel) {
+ return new Cost(jn.computeJoinCardinality());
+ }
+
+ public Cost costIndexDataScan(JoinNode jn, double indexSel) {
return new Cost(jn.computeJoinCardinality());
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/ICostMethods.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/ICostMethods.java
index 47ef617..ef4af41 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/ICostMethods.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/ICostMethods.java
@@ -24,7 +24,7 @@
public interface ICostMethods {
Cost costFullScan(JoinNode jn);
- Cost costIndexScan(JoinNode jn);
+ Cost costIndexScan(JoinNode jn, double indexSel);
Cost costHashJoin(JoinNode currentJn);
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/ContainsExpressionVisitor.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/ContainsExpressionVisitor.java
new file mode 100644
index 0000000..6016949
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/ContainsExpressionVisitor.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.asterix.optimizer.rules.cbo;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.visitors.ILogicalExpressionReferenceTransform;
+
+public class ContainsExpressionVisitor implements ILogicalExpressionReferenceTransform {
+ private ILogicalExpression expr;
+
+ protected void setExpression(ILogicalExpression expr) {
+ this.expr = expr;
+ }
+
+ @Override
+ public boolean transform(Mutable<ILogicalExpression> exprRef) throws AlgebricksException {
+ ILogicalExpression expression = exprRef.getValue();
+ boolean result = expr.equals(expression);
+
+ if (!result && expression.getExpressionTag() == LogicalExpressionTag.FUNCTION_CALL) {
+ AbstractFunctionCallExpression funcExpr = (AbstractFunctionCallExpression) expression;
+ for (Mutable<ILogicalExpression> arg : funcExpr.getArguments()) {
+ if (transform(arg)) {
+ return true;
+ }
+ }
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
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 8ea1452..f2319c4 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
@@ -67,7 +67,7 @@
private static final Logger LOGGER = LogManager.getLogger();
- protected final JoinEnum joinEnum;
+ private final JoinEnum joinEnum;
public EnumerateJoinsRule(JoinEnum joinEnum) {
this.joinEnum = joinEnum;
@@ -602,7 +602,7 @@
return root;
}
- public static void printPlan(IPlanPrettyPrinter pp, AbstractLogicalOperator op, String text)
+ protected static void printPlan(IPlanPrettyPrinter pp, AbstractLogicalOperator op, String text)
throws AlgebricksException {
if (LOGGER.isTraceEnabled()) {
pp.reset();
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinCondition.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinCondition.java
index bc7ea3f..7cf1ebd 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinCondition.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinCondition.java
@@ -23,27 +23,27 @@
public class JoinCondition {
- public static final int NO_JC = -1;
+ protected static final int NO_JC = -1;
- public ILogicalExpression joinCondition;
- public boolean derived = false;
- public boolean partOfComposite = false;
- public int numberOfVars = 0; // how many variables
- public int componentNumber = 0; // for identifying if join graph is connected
- public int datasetBits;
+ protected ILogicalExpression joinCondition;
+ private boolean derived = false;
+ protected boolean partOfComposite = false;
+ protected int numberOfVars = 0; // how many variables
+ protected int componentNumber = 0; // for identifying if join graph is connected
+ protected int datasetBits;
// used for triangle detection; we strictly do not mean left and right here.
// first and second sides would be more appropriate
- public int leftSideBits;
- public int rightSideBits;
- public double selectivity;
- public comparisonOp comparisonType;
+ protected int leftSideBits;
+ protected int rightSideBits;
+ protected double selectivity;
+ protected comparisonOp comparisonType;
- public enum comparisonOp {
+ protected enum comparisonOp {
OP_EQ,
OP_OTHER
}
- public ILogicalExpression getJoinCondition() {
+ protected ILogicalExpression getJoinCondition() {
return joinCondition;
}
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java
index 891c82d..46a67e8 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java
@@ -30,9 +30,15 @@
import org.apache.asterix.common.annotations.IndexedNLJoinExpressionAnnotation;
import org.apache.asterix.common.annotations.SecondaryIndexSearchPreferenceAnnotation;
+import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.metadata.declared.DataSource;
import org.apache.asterix.metadata.declared.DataSourceId;
+import org.apache.asterix.metadata.declared.DatasetDataSource;
+import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.metadata.declared.SampleDataSource;
import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.om.base.AInt64;
import org.apache.asterix.om.base.AOrderedList;
import org.apache.asterix.om.base.IAObject;
import org.apache.asterix.om.constants.AsterixConstantValue;
@@ -57,6 +63,7 @@
import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.HashJoinExpressionAnnotation;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionAnnotation;
+import org.apache.hyracks.algebricks.core.algebra.expressions.PredicateCardinalityAnnotation;
import org.apache.hyracks.algebricks.core.algebra.expressions.ScalarFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
@@ -66,11 +73,13 @@
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.InnerJoinOperator;
+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.prettyprint.IPlanPrettyPrinter;
import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil;
import org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
+import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.exceptions.Warning;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -84,19 +93,19 @@
protected List<PlanNode> allPlans; // list of all plans
protected JoinNode[] jnArray; // array of all join nodes
protected int jnArraySize;
- protected List<Pair<EmptyTupleSourceOperator, DataSourceScanOperator>> emptyTupleAndDataSourceOps;
+ private List<Pair<EmptyTupleSourceOperator, DataSourceScanOperator>> emptyTupleAndDataSourceOps;
protected Map<EmptyTupleSourceOperator, ILogicalOperator> joinLeafInputsHashMap;
protected List<ILogicalExpression> singleDatasetPreds;
- protected List<AssignOperator> assignOps;
- protected List<ILogicalOperator> joinOps;
+ private List<AssignOperator> assignOps;
+ private List<ILogicalOperator> joinOps;
protected ILogicalOperator localJoinOp; // used in nestedLoopsApplicable code.
protected IOptimizationContext optCtx;
+
protected Stats stats;
- protected PhysicalOptimizationConfig physOptConfig;
- protected boolean cboMode;
- protected boolean cboTestMode;
+ private boolean cboMode;
+ private boolean cboTestMode;
protected int numberOfTerms;
- protected AbstractLogicalOperator op;
+ private AbstractLogicalOperator op;
protected boolean connectedJoinGraph;
protected boolean forceJoinOrderMode;
protected String queryPlanShape;
@@ -106,13 +115,12 @@
public JoinEnum() {
}
- public void initEnum(AbstractLogicalOperator op, boolean cboMode, boolean cboTestMode, int numberOfFromTerms,
+ protected void initEnum(AbstractLogicalOperator op, boolean cboMode, boolean cboTestMode, int numberOfFromTerms,
List<Pair<EmptyTupleSourceOperator, DataSourceScanOperator>> emptyTupleAndDataSourceOps,
Map<EmptyTupleSourceOperator, ILogicalOperator> joinLeafInputsHashMap, List<ILogicalOperator> joinOps,
List<AssignOperator> assignOps, IOptimizationContext context) {
this.singleDatasetPreds = new ArrayList<>();
this.joinConditions = new ArrayList<>();
- this.assignOps = new ArrayList<>();
this.joinHints = new HashMap<>();
this.allPlans = new ArrayList<>();
this.numberOfTerms = numberOfFromTerms;
@@ -120,7 +128,6 @@
this.cboTestMode = cboTestMode;
this.connectedJoinGraph = true;
this.optCtx = context;
- this.physOptConfig = context.getPhysicalOptimizationConfig();
this.emptyTupleAndDataSourceOps = emptyTupleAndDataSourceOps;
this.joinLeafInputsHashMap = joinLeafInputsHashMap;
this.assignOps = assignOps;
@@ -143,7 +150,7 @@
}
}
- public List<JoinCondition> getJoinConditions() {
+ protected List<JoinCondition> getJoinConditions() {
return joinConditions;
}
@@ -151,27 +158,23 @@
return allPlans;
}
- public JoinNode[] getJnArray() {
+ protected JoinNode[] getJnArray() {
return jnArray;
}
- public Cost getCostHandle() {
+ protected Cost getCostHandle() {
return (Cost) cost;
}
- public CostMethods getCostMethodsHandle() {
+ protected CostMethods getCostMethodsHandle() {
return (CostMethods) costMethods;
}
- public Stats getStatsHandle() {
+ protected Stats getStatsHandle() {
return stats;
}
- public Map<EmptyTupleSourceOperator, ILogicalOperator> getJoinLeafInputsHashMap() {
- return joinLeafInputsHashMap;
- }
-
- public ILogicalOperator findLeafInput(List<LogicalVariable> logicalVars) throws AlgebricksException {
+ protected ILogicalOperator findLeafInput(List<LogicalVariable> logicalVars) throws AlgebricksException {
Set<LogicalVariable> vars = new HashSet<>();
for (Pair<EmptyTupleSourceOperator, DataSourceScanOperator> emptyTupleAndDataSourceOp : emptyTupleAndDataSourceOps) {
EmptyTupleSourceOperator emptyOp = emptyTupleAndDataSourceOp.getFirst();
@@ -187,7 +190,7 @@
return null;
}
- public ILogicalExpression combineAllConditions(List<Integer> newJoinConditions) {
+ protected ILogicalExpression combineAllConditions(List<Integer> newJoinConditions) {
if (newJoinConditions.size() == 0) {
// this is a cartesian product
return ConstantExpression.TRUE;
@@ -207,7 +210,7 @@
return andExpr;
}
- public ILogicalExpression getNestedLoopJoinExpr(List<Integer> newJoinConditions) {
+ protected ILogicalExpression getNestedLoopJoinExpr(List<Integer> newJoinConditions) {
if (newJoinConditions.size() != 1) {
// may remove this restriction later if possible
return null;
@@ -216,7 +219,7 @@
return jc.joinCondition;
}
- public ILogicalExpression getHashJoinExpr(List<Integer> newJoinConditions) {
+ protected ILogicalExpression getHashJoinExpr(List<Integer> newJoinConditions) {
if (newJoinConditions.size() == 0) {
// this is a cartesian product
return ConstantExpression.TRUE;
@@ -245,7 +248,7 @@
return eqPredFound ? andExpr : null;
}
- public HashJoinExpressionAnnotation findHashJoinHint(List<Integer> newJoinConditions) {
+ protected HashJoinExpressionAnnotation findHashJoinHint(List<Integer> newJoinConditions) {
for (int i : newJoinConditions) {
JoinCondition jc = joinConditions.get(i);
if (jc.comparisonType != JoinCondition.comparisonOp.OP_EQ) {
@@ -263,7 +266,7 @@
return null;
}
- public BroadcastExpressionAnnotation findBroadcastHashJoinHint(List<Integer> newJoinConditions) {
+ protected BroadcastExpressionAnnotation findBroadcastHashJoinHint(List<Integer> newJoinConditions) {
for (int i : newJoinConditions) {
JoinCondition jc = joinConditions.get(i);
if (jc.comparisonType != JoinCondition.comparisonOp.OP_EQ) {
@@ -281,7 +284,7 @@
return null;
}
- public IndexedNLJoinExpressionAnnotation findNLJoinHint(List<Integer> newJoinConditions) {
+ protected IndexedNLJoinExpressionAnnotation findNLJoinHint(List<Integer> newJoinConditions) {
for (int i : newJoinConditions) {
JoinCondition jc = joinConditions.get(i);
ILogicalExpression expr = jc.joinCondition;
@@ -316,7 +319,7 @@
return false;
}
- public int findJoinNodeIndexByName(String name) {
+ protected int findJoinNodeIndexByName(String name) {
for (int i = 1; i <= this.numberOfTerms; i++) {
if (name.equals(jnArray[i].datasetNames.get(0))) {
return i;
@@ -328,7 +331,7 @@
return JoinNode.NO_JN;
}
- public int findJoinNodeIndex(LogicalVariable lv) throws AlgebricksException {
+ protected int findJoinNodeIndex(LogicalVariable lv) throws AlgebricksException {
List<Pair<EmptyTupleSourceOperator, DataSourceScanOperator>> emptyTupleAndDataSourceOps =
this.emptyTupleAndDataSourceOps;
Map<EmptyTupleSourceOperator, ILogicalOperator> joinLeafInputsHashMap = this.joinLeafInputsHashMap;
@@ -372,7 +375,7 @@
// This finds all the join Conditions in the whole query. This is a global list of all join predicates.
// It also fills in the dataset Bits for each join predicate.
- protected void findJoinConditions() throws AlgebricksException {
+ private void findJoinConditionsAndAssignSels() throws AlgebricksException {
List<Mutable<ILogicalExpression>> conjs = new ArrayList<>();
for (ILogicalOperator jOp : joinOps) {
AbstractBinaryJoinOperator joinOp = (AbstractBinaryJoinOperator) jOp;
@@ -418,15 +421,6 @@
// now fill the datasetBits for each join condition.
for (JoinCondition jc : joinConditions) {
ILogicalExpression joinExpr = jc.joinCondition;
- /*
- if (joinExpr.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
- AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) joinExpr;
- // remove all the join method type annotations.
- afce.removeAnnotation(BroadcastExpressionAnnotation.class);
- afce.removeAnnotation(IndexedNLJoinExpressionAnnotation.class);
- afce.removeAnnotation(HashJoinExpressionAnnotation.class);
- }
- */
usedVars.clear();
joinExpr.getUsedVariables(usedVars);
// We only set these for join predicates that have exactly two tables
@@ -646,27 +640,7 @@
return jnNumber;
}
- protected int enumerateBaseLevelJoinNodes() throws AlgebricksException {
- int lastBaseLevelJnNum = initializeBaseLevelJoinNodes();
- if (lastBaseLevelJnNum == PlanNode.NO_PLAN) {
- return PlanNode.NO_PLAN;
- }
- int dataScanPlan = PlanNode.NO_PLAN;
- for (int i = 1; i <= numberOfTerms; i++) {
- JoinNode jn = jnArray[i];
- EmptyTupleSourceOperator ets = emptyTupleAndDataSourceOps.get(i - 1).getFirst();
- ILogicalOperator leafInput = joinLeafInputsHashMap.get(ets);
- dataScanPlan = jn.addSingleDatasetPlans();
- if (dataScanPlan == PlanNode.NO_PLAN) {
- return PlanNode.NO_PLAN;
- }
- // We may not add any index plans, so need to check for NO_PLAN
- jn.addIndexAccessPlans(leafInput);
- }
- return numberOfTerms;
- }
-
- protected int initializeBaseLevelJoinNodes() throws AlgebricksException {
+ private int initializeBaseLevelJoinNodes() throws AlgebricksException {
// join nodes have been allocated in the JoinEnum
// add a dummy Plan Node; we do not want planNode at position 0 to be a valid plan
PlanNode pn = new PlanNode(0, this);
@@ -738,8 +712,212 @@
return numberOfTerms;
}
+ // Most of this work is done in the very first line by calling initializeBaseLevelJoinNodes().
+ // the remaining work here is to find the selectivities of the predicates using sampling.
+ // By the time execution reaches this point, samples are guaranteed to exist on all datasets,
+ // so some of the checks can be removed.
+ private int enumerateBaseLevelJoinNodes() throws AlgebricksException {
+ int lastBaseLevelJnNum = initializeBaseLevelJoinNodes(); // initialize the level 1 join nodes
+ if (lastBaseLevelJnNum == PlanNode.NO_PLAN) {
+ return PlanNode.NO_PLAN;
+ }
+
+ int dataScanPlan;
+ JoinNode[] jnArray = this.getJnArray();
+ for (int i = 1; i <= this.numberOfTerms; i++) {
+ JoinNode jn = jnArray[i];
+ Index.SampleIndexDetails idxDetails = jn.getIdxDetails();
+ EmptyTupleSourceOperator ets = this.emptyTupleAndDataSourceOps.get(i - 1).getFirst();
+ ILogicalOperator leafInput = this.joinLeafInputsHashMap.get(ets);
+ if (!cboTestMode) {
+ if (idxDetails == null) {
+ continue;
+ }
+ double origDatasetCard, finalDatasetCard, sampleCard;
+
+ ILogicalOperator parent = findDataSourceScanOperatorParent(leafInput);
+ DataSourceScanOperator scanOp = this.emptyTupleAndDataSourceOps.get(i - 1).getSecond();
+ if (scanOp == null) {
+ continue; // what happens to the cards and sizes then? this may happen in case of in lists
+ }
+
+ finalDatasetCard = origDatasetCard = idxDetails.getSourceCardinality();
+
+ List<List<IAObject>> result;
+ SelectOperator selop = (SelectOperator) findASelectOp(leafInput);
+
+ if (jn.getCardinality() == jn.getOrigCardinality() && selop != null) { // this means there was no selectivity hint provided
+ SampleDataSource sampledatasource = getSampleDataSource(scanOp);
+ DataSourceScanOperator deepCopyofScan =
+ (DataSourceScanOperator) OperatorManipulationUtil.bottomUpCopyOperators(scanOp);
+ deepCopyofScan.setDataSource(sampledatasource);
+
+ // if there is only one conjunct, I do not have to call the sampling query during index selection!
+ // insert this in place of the scandatasourceOp.
+ parent.getInputs().get(0).setValue(deepCopyofScan);
+ // There are predicates here. So skip the predicates and get the original dataset card.
+ // Now apply all the predicates and get the card after all predicates are applied.
+ result = stats.runSamplingQuery(this.optCtx, leafInput);
+ double predicateCardinality = ((double) ((AInt64) result.get(0).get(0)).getLongValue());
+ if (predicateCardinality == 0.0) {
+ predicateCardinality = 0.0001 * idxDetails.getSampleCardinalityTarget();
+ }
+ // now scale up
+ sampleCard = Math.min(idxDetails.getSampleCardinalityTarget(), origDatasetCard);
+ if (sampleCard == 0) { // should not happen unless the original dataset is empty
+ sampleCard = 1; // we may have to make some adjustments to costs when the sample returns very rows.
+
+ IWarningCollector warningCollector = optCtx.getWarningCollector();
+ if (warningCollector.shouldWarn()) {
+ warningCollector
+ .warn(Warning.of(scanOp.getSourceLocation(), ErrorCode.SAMPLE_HAS_ZERO_ROWS));
+ }
+ }
+
+ finalDatasetCard *= predicateCardinality / sampleCard;
+ // now switch the input back.
+ parent.getInputs().get(0).setValue(scanOp);
+ jn.setCardinality(finalDatasetCard);
+ }
+ }
+ dataScanPlan = jn.addSingleDatasetPlans();
+ if (dataScanPlan == PlanNode.NO_PLAN) {
+ return PlanNode.NO_PLAN;
+ }
+ // We may not add any index plans, so need to check for NO_PLAN
+ jn.addIndexAccessPlans(leafInput);
+ }
+ return this.numberOfTerms;
+ }
+
+ private boolean isPredicateCardinalityAnnotationPresent(ILogicalExpression leExpr) {
+ if (leExpr.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
+ AbstractFunctionCallExpression afcExpr = (AbstractFunctionCallExpression) leExpr;
+ PredicateCardinalityAnnotation pca = afcExpr.getAnnotation(PredicateCardinalityAnnotation.class);
+ if (pca != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // Since we need to switch the datasource to the sample, we need the parent, so we can do the necessary
+ // linked list manipulation.
+ protected ILogicalOperator findDataSourceScanOperatorParent(ILogicalOperator op) {
+ ILogicalOperator parent = op;
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.DATASOURCESCAN)) {
+ return parent;
+ }
+ parent = op;
+ op = op.getInputs().get(0).getValue();
+ }
+ return null;
+ }
+
+ // we need to switch the datascource from the dataset source to the corresponding sample datasource.
+ // Little tricky how this is done!
+ protected SampleDataSource getSampleDataSource(DataSourceScanOperator scanOp) throws AlgebricksException {
+ DataverseName dataverseName = stats.findDataverseName(scanOp);
+ DataSource ds = (DataSource) scanOp.getDataSource();
+ DataSourceId dsid = ds.getId();
+ MetadataProvider mdp = (MetadataProvider) this.optCtx.getMetadataProvider();
+ Index index = mdp.findSampleIndex(dataverseName, dsid.getDatasourceName());
+ DatasetDataSource dds = (DatasetDataSource) ds;
+ SampleDataSource sds = new SampleDataSource(dds.getDataset(), index.getIndexName(), ds.getItemType(),
+ ds.getMetaItemType(), ds.getDomain());
+ return sds;
+ }
+
+ private ILogicalOperator findASelectOp(ILogicalOperator op) {
+
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+
+ if (op.getOperatorTag() == LogicalOperatorTag.SELECT) {
+ return op;
+ }
+
+ op = op.getInputs().get(0).getValue();
+ }
+ return null;
+ }
+
+ // Find the join conditions. Assign selectivities to the join conditions from any user provided annotation hints.
+ // If there are no annotation hints, use samples to find the selectivities of the single table predicates
+ // found inside of complex join predicates (as in q7). A lot of extra code has gone into making q7 work.
+ private void findJoinConditions() throws AlgebricksException {
+ findJoinConditionsAndAssignSels();
+ List<List<IAObject>> result;
+ double predicateCardinality;
+ // for all the singleVarExprs, we need to issue a sample query. These exprs did not get assigned a selectivity.
+ for (ILogicalExpression exp : this.singleDatasetPreds) {
+ if (isPredicateCardinalityAnnotationPresent(exp)) {
+ continue; // no need to get selectivity from sample in case of user provided hints.
+ }
+ List<LogicalVariable> vars = new ArrayList<>();
+ exp.getUsedVariables(vars);
+ if (vars.size() == 1) { // just being really safe. If samples have size 0, there are issues.
+ double origDatasetCard, finalDatasetCard, sampleCard, predicateCard;
+ ILogicalOperator leafInput = findLeafInput(vars);
+ ILogicalOperator parent = findDataSourceScanOperatorParent(leafInput);
+ DataSourceScanOperator scanOp = (DataSourceScanOperator) parent.getInputs().get(0).getValue();
+
+ if (scanOp == null) {
+ continue; // what happens to the cards and sizes then? this may happen in case of in lists
+ }
+
+ Index index = getStatsHandle().findSampleIndex(scanOp, this.optCtx);
+ if (index == null) {
+ continue; // no sample found
+ }
+ Index.SampleIndexDetails idxDetails = (Index.SampleIndexDetails) index.getIndexDetails();
+ origDatasetCard = idxDetails.getSourceCardinality();
+ sampleCard = Math.min(idxDetails.getSampleCardinalityTarget(), origDatasetCard); // handle datasets whose card is small
+ if (sampleCard == 0) {
+ sampleCard = 1;
+ IWarningCollector warningCollector = optCtx.getWarningCollector();
+ if (warningCollector.shouldWarn()) {
+ warningCollector.warn(Warning.of(scanOp.getSourceLocation(), ErrorCode.SAMPLE_HAS_ZERO_ROWS));
+ }
+ }
+
+ // replace the dataScanSourceOperator with the sampling source
+ SampleDataSource sampledatasource = getSampleDataSource(scanOp);
+ DataSourceScanOperator deepCopyofScan =
+ (DataSourceScanOperator) OperatorManipulationUtil.bottomUpCopyOperators(scanOp);
+ deepCopyofScan.setDataSource(sampledatasource);
+
+ // insert this in place of the scandatasourceOp.
+ parent.getInputs().get(0).setValue(deepCopyofScan);
+
+ // Need to add a selectOperator on top of leafInput.
+ SelectOperator selOp = new SelectOperator(new MutableObject<>(exp));
+ selOp.getInputs().add(new MutableObject<>(leafInput));
+ result = stats.runSamplingQuery(this.optCtx, selOp);
+ predicateCardinality = ((double) ((AInt64) result.get(0).get(0)).getLongValue());
+ if (predicateCardinality == 0.0) {
+ predicateCardinality = 0.0001 * idxDetails.getSampleCardinalityTarget();
+ }
+
+ PredicateCardinalityAnnotation anno =
+ new PredicateCardinalityAnnotation(predicateCardinality / sampleCard);
+ AbstractFunctionCallExpression afce = (AbstractFunctionCallExpression) exp;
+ afce.putAnnotation(anno);
+ // now switch the input back.
+ parent.getInputs().get(0).setValue(scanOp);
+ }
+ }
+
+ if (this.singleDatasetPreds.size() > 0) { // We did not have selectivities for these before. Now we do.
+ for (JoinCondition jc : joinConditions) {
+ jc.selectivity = stats.getSelectivityFromAnnotationMain(jc.getJoinCondition(), false);
+ // we may be repeating some work here, but that is ok. This will rarely happen (happens in q7 tpch)
+ }
+ }
+ }
+
// main entry point in this file
- public int enumerateJoins() throws AlgebricksException {
+ protected int enumerateJoins() throws AlgebricksException {
// create a localJoinOp for use in calling existing nested loops code.
InnerJoinOperator dummyInput = new InnerJoinOperator(null, null, null);
localJoinOp = new InnerJoinOperator(new MutableObject<>(ConstantExpression.TRUE),
@@ -792,12 +970,12 @@
return sb.toString();
}
- public static boolean getForceJoinOrderMode(IOptimizationContext context) {
+ private static boolean getForceJoinOrderMode(IOptimizationContext context) {
PhysicalOptimizationConfig physOptConfig = context.getPhysicalOptimizationConfig();
return physOptConfig.getForceJoinOrderMode();
}
- public static String getQueryPlanShape(IOptimizationContext context) {
+ private static String getQueryPlanShape(IOptimizationContext context) {
PhysicalOptimizationConfig physOptConfig = context.getPhysicalOptimizationConfig();
return physOptConfig.getQueryPlanShapeMode();
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java
index 417f178..fa2a144 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinNode.java
@@ -20,7 +20,9 @@
package org.apache.asterix.optimizer.rules.cbo;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -29,6 +31,7 @@
import org.apache.asterix.common.annotations.IndexedNLJoinExpressionAnnotation;
import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
+import org.apache.asterix.common.config.DatasetConfig;
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.om.functions.BuiltinFunctions;
import org.apache.asterix.optimizer.cost.Cost;
@@ -41,6 +44,7 @@
import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.common.utils.Triple;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
@@ -66,7 +70,6 @@
public class JoinNode {
private static final Logger LOGGER = LogManager.getLogger();
-
protected JoinEnum joinEnum;
protected int jnArrayIndex;
protected int datasetBits; // this is bitmap of all the keyspaceBits present in this joinNode
@@ -74,73 +77,52 @@
protected List<String> datasetNames;
protected List<String> aliases;
protected int cheapestPlanIndex;
- protected ICost cheapestPlanCost;
+ private ICost cheapestPlanCost;
protected double origCardinality; // without any selections
protected double cardinality;
protected double size;
protected List<Integer> planIndexesArray; // indexes into the PlanNode array in enumerateJoins
- protected int jnIndex, level, highestDatasetId;
- protected JoinNode rightJn, leftJn;
- protected List<Integer> applicableJoinConditions;
+ protected int jnIndex;
+ protected int level;
+ protected int highestDatasetId;
+ private JoinNode rightJn;
+ private JoinNode leftJn;
+ private List<Integer> applicableJoinConditions;
protected EmptyTupleSourceOperator correspondingEmptyTupleSourceOp; // There is a 1-1 relationship between the LVs and the dataSourceScanOps and the leafInputs.
- protected List<Pair<IAccessMethod, Index>> chosenIndexes;
- protected Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs;
+ private List<Pair<IAccessMethod, Index>> chosenIndexes;
+ private Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs;
protected Index.SampleIndexDetails idxDetails;
+ private List<Triple<Index, Double, AbstractFunctionCallExpression>> IndexCostInfo;
+ // The triple above is : Index, selectivity, and the index expression
protected static int NO_JN = -1;
- protected static int NO_CARDS = -2;
+ private static int NO_CARDS = -2;
- public JoinNode(int i) {
+ private JoinNode(int i) {
this.jnArrayIndex = i;
planIndexesArray = new ArrayList<>();
cheapestPlanIndex = PlanNode.NO_PLAN;
size = 1; // for now, will be the size of the doc for this joinNode
}
- public JoinNode(int i, JoinEnum joinE) {
+ protected JoinNode(int i, JoinEnum joinE) {
this(i);
joinEnum = joinE;
cheapestPlanCost = joinEnum.getCostHandle().maxCost();
}
- public boolean IsBaseLevelJoinNode() {
+ protected boolean IsBaseLevelJoinNode() {
return this.jnArrayIndex <= joinEnum.numberOfTerms;
}
- public boolean IsHigherLevelJoinNode() {
+ protected boolean IsHigherLevelJoinNode() {
return !IsBaseLevelJoinNode();
}
- public double computeJoinCardinality() {
- JoinNode[] jnArray = joinEnum.getJnArray();
- List<JoinCondition> joinConditions = joinEnum.getJoinConditions();
-
- this.applicableJoinConditions = new ArrayList<>();
- findApplicableJoinConditions();
-
- if (LOGGER.isTraceEnabled() && this.applicableJoinConditions.size() == 0) {
- LOGGER.trace("applicable Join Conditions size is 0 in join Node " + this.jnArrayIndex);
- }
-
- // Wonder if this computation will result in an overflow exception. Better to multiply them with selectivities also.
- double productJoinCardinality = 1.0;
- for (int idx : this.datasetIndexes) {
- productJoinCardinality *= jnArray[idx].cardinality;
- }
-
- double productJoinSels = 1.0;
- for (int idx : this.applicableJoinConditions) {
- if (!joinConditions.get(idx).partOfComposite) {
- productJoinSels *= joinConditions.get(idx).selectivity;
- }
- }
- return productJoinCardinality * productJoinSels;
- }
-
public double getCardinality() {
return cardinality;
}
- public void setCardinality(double card) {
+ protected void setCardinality(double card) {
cardinality = card;
}
@@ -148,11 +130,11 @@
return origCardinality;
}
- public void setOrigCardinality(double card) {
+ protected void setOrigCardinality(double card) {
origCardinality = card;
}
- public void setAvgDocSize(double avgDocSize) {
+ protected void setAvgDocSize(double avgDocSize) {
size = avgDocSize;
}
@@ -172,19 +154,19 @@
return rightJn;
}
- public List<String> getAliases() {
+ private List<String> getAliases() {
return aliases;
}
- public List<String> getDatasetNames() {
+ protected List<String> getDatasetNames() {
return datasetNames;
}
- public Index.SampleIndexDetails getIdxDetails() {
+ protected Index.SampleIndexDetails getIdxDetails() {
return idxDetails;
}
- protected boolean nestedLoopsApplicable(ILogicalExpression joinExpr) throws AlgebricksException {
+ private boolean nestedLoopsApplicable(ILogicalExpression joinExpr) throws AlgebricksException {
List<LogicalVariable> usedVarList = new ArrayList<>();
joinExpr.getUsedVariables(usedVarList);
@@ -243,7 +225,7 @@
return (one & two) == one;
}
- protected void findApplicableJoinConditions() {
+ private void findApplicableJoinConditions() {
List<JoinCondition> joinConditions = joinEnum.getJoinConditions();
int i = 0;
@@ -255,7 +237,7 @@
}
}
- protected List<Integer> getNewJoinConditionsOnly() {
+ private List<Integer> getNewJoinConditionsOnly() {
List<Integer> newJoinConditions = new ArrayList<>();
JoinNode leftJn = this.leftJn;
JoinNode rightJn = this.rightJn;
@@ -281,7 +263,121 @@
return newJoinConditions; // this can be of size 0 because this may be a cartesian join
}
- public int addSingleDatasetPlans() {
+ public double computeJoinCardinality() {
+ JoinNode[] jnArray = joinEnum.getJnArray();
+ List<JoinCondition> joinConditions = joinEnum.getJoinConditions();
+ double joinCard;
+
+ this.applicableJoinConditions = new ArrayList<>();
+ findApplicableJoinConditions();
+
+ if (LOGGER.isTraceEnabled() && this.applicableJoinConditions.size() == 0) {
+ LOGGER.trace("applicable Join Conditions size is 0 in join Node " + this.jnArrayIndex);
+ }
+
+ // Wonder if this computation will result in an overflow exception. Better to multiply them with selectivities also.
+ double productJoinCardinality = 1.0;
+ for (int idx : this.datasetIndexes) {
+ productJoinCardinality *= jnArray[idx].cardinality;
+ }
+
+ double productJoinSels = 1.0;
+ for (int idx : this.applicableJoinConditions) {
+ if (!joinConditions.get(idx).partOfComposite) {
+ productJoinSels *= joinConditions.get(idx).selectivity;
+ }
+ }
+ joinCard = productJoinCardinality * productJoinSels;
+
+ double redundantSel = 1.0;
+ // Now see if any redundant edges are present; R.a = S.a and S.a = T.a ==> R.a = T.a.
+ // One of them must be removed to estimate cardinality correctly.
+ if (this.applicableJoinConditions.size() >= 3) {
+ redundantSel = removeRedundantPred(this.applicableJoinConditions);
+ }
+
+ // By dividing by redundantSel, we are undoing the earlier multiplication of all the selectivities.
+ return joinCard / redundantSel;
+ }
+
+ private static double adjustSelectivities(JoinCondition jc1, JoinCondition jc2, JoinCondition jc3) {
+ double sel;
+ if (jc1.comparisonType == JoinCondition.comparisonOp.OP_EQ
+ && jc2.comparisonType == JoinCondition.comparisonOp.OP_EQ
+ && jc3.comparisonType == JoinCondition.comparisonOp.OP_EQ) {
+ sel = findRedundantSel(jc1.selectivity, jc2.selectivity, jc3.selectivity);
+ } else {
+ // at least one of the predicates in not an equality predicate
+ //this can get messy here, as 1, or 2 or all 3 can be non equality
+ // we will just drop the first one we find now
+ if (jc1.comparisonType != JoinCondition.comparisonOp.OP_EQ) {
+ sel = jc1.selectivity;
+ } else if (jc2.comparisonType != JoinCondition.comparisonOp.OP_EQ) {
+ sel = jc2.selectivity;
+ } else {
+ sel = jc3.selectivity;
+ }
+ }
+ return sel;
+ }
+
+ // if a redundant edge is found, we need to eliminate one of the edges.
+ // If two triangles share an edge, removing the common edge will suffice
+ // Each edge has two vertices. So we can only handle predicate with exactly two tables such as R.a = S.a
+ // We will not handle cases such as R.a + S.a = T.a
+ // It should be easy to identify two vertex edges as only two bits will be set for such conditions.
+ private double removeRedundantPred(List<Integer> applicablePredicatesInCurrentJn) {
+ double redundantSel = 1.0;
+ List<JoinCondition> joinConditions = joinEnum.getJoinConditions();
+ JoinCondition jc1, jc2, jc3;
+ int[] vertices = new int[6];
+ int[] verticesCopy = new int[6];
+ for (int i = 0; i <= applicablePredicatesInCurrentJn.size() - 3; i++) {
+ jc1 = joinConditions.get(applicablePredicatesInCurrentJn.get(i));
+ if (jc1.partOfComposite) {
+ continue; // must ignore these or the same triangles will be found more than once.
+ }
+ vertices[0] = jc1.leftSideBits;
+ vertices[1] = jc1.rightSideBits;
+ for (int j = i + 1; j <= applicablePredicatesInCurrentJn.size() - 2; j++) {
+ jc2 = joinConditions.get(applicablePredicatesInCurrentJn.get(j));
+ if (jc2.partOfComposite) {
+ continue;
+ }
+ vertices[2] = jc2.leftSideBits;
+ vertices[3] = jc2.rightSideBits;
+ for (int k = j + 1; k <= applicablePredicatesInCurrentJn.size() - 1; k++) {
+ jc3 = joinConditions.get(applicablePredicatesInCurrentJn.get(k));
+ if (jc3.partOfComposite) {
+ continue;
+ }
+ vertices[4] = jc3.leftSideBits;
+ vertices[5] = jc3.rightSideBits;
+
+ System.arraycopy(vertices, 0, verticesCopy, 0, 6);
+ Arrays.sort(verticesCopy);
+ if (verticesCopy[0] == verticesCopy[1] && verticesCopy[2] == verticesCopy[3]
+ && verticesCopy[4] == verticesCopy[5]) {
+ // redundant edge found
+ redundantSel *= adjustSelectivities(jc1, jc2, jc3);
+ }
+ }
+ }
+ }
+ return redundantSel;
+ }
+
+ private static double findRedundantSel(double sel1, double sel2, double sel3) {
+ double[] sels = new double[3];
+ sels[0] = sel1;
+ sels[1] = sel2;
+ sels[2] = sel3;
+
+ Arrays.sort(sels); // we are sorting to make this deterministic
+ return sels[1]; // the middle one is closest to one of the extremes
+ }
+
+ protected int addSingleDatasetPlans() {
List<PlanNode> allPlans = joinEnum.allPlans;
ICost opCost, totalCost;
@@ -290,58 +386,61 @@
if (this.cheapestPlanIndex == PlanNode.NO_PLAN || opCost.costLT(this.cheapestPlanCost)) {
// for now just add one plan
PlanNode pn = new PlanNode(allPlans.size(), joinEnum);
- pn.jn = this;
+ pn.setJoinNode(this);
pn.datasetName = this.datasetNames.get(0);
pn.correspondingEmptyTupleSourceOp = this.correspondingEmptyTupleSourceOp;
- pn.jnIndexes[0] = this.jnArrayIndex;
- pn.jnIndexes[1] = JoinNode.NO_JN;
- pn.planIndexes[0] = PlanNode.NO_PLAN; // There ane no plans below this plan.
- pn.planIndexes[1] = PlanNode.NO_PLAN; // There ane no plans below this plan.
+ pn.setLeftJoinIndex(this.jnArrayIndex);
+ pn.setRightJoinIndex(JoinNode.NO_JN);
+ pn.setLeftPlanIndex(PlanNode.NO_PLAN); // There ane no plans below this plan.
+ pn.setRightPlanIndex(PlanNode.NO_PLAN); // There ane no plans below this plan.
pn.opCost = opCost;
pn.scanOp = PlanNode.ScanMethod.TABLE_SCAN;
pn.totalCost = totalCost;
allPlans.add(pn);
- this.planIndexesArray.add(allPlans.size() - 1);
+ this.planIndexesArray.add(pn.allPlansIndex);
this.cheapestPlanCost = totalCost;
- this.cheapestPlanIndex = allPlans.size() - 1;
+ this.cheapestPlanIndex = pn.allPlansIndex;
return this.cheapestPlanIndex;
}
return PlanNode.NO_PLAN;
}
- protected void buildIndexPlan(boolean forceIndexPlan) {
- List<PlanNode> allPlans = joinEnum.allPlans;
- ICost opCost, totalCost;
+ private AbstractFunctionCallExpression buildExpr(List<IOptimizableFuncExpr> exprs,
+ List<Pair<Integer, Integer>> pairs) {
+ int i;
+ if (pairs.size() == 1) {
+ i = pairs.get(0).getFirst();
+ return exprs.get(i).getFuncExpr();
+ }
- opCost = joinEnum.getCostMethodsHandle().costIndexScan(this);
- totalCost = opCost;
- if (this.cheapestPlanIndex == PlanNode.NO_PLAN || opCost.costLT(this.cheapestPlanCost) || forceIndexPlan) {
- // for now just add one plan
- PlanNode pn = new PlanNode(allPlans.size(), joinEnum);
- pn.jn = this;
- pn.datasetName = this.datasetNames.get(0);
- pn.correspondingEmptyTupleSourceOp = this.correspondingEmptyTupleSourceOp;
- pn.jnIndexes[0] = this.jnArrayIndex;
- pn.jnIndexes[1] = JoinNode.NO_JN;
- pn.planIndexes[0] = PlanNode.NO_PLAN; // There ane no plans below this plan.
- pn.planIndexes[1] = PlanNode.NO_PLAN; // There ane no plans below this plan.
- pn.opCost = opCost;
- pn.scanOp = PlanNode.ScanMethod.INDEX_SCAN;
- pn.totalCost = totalCost;
+ ScalarFunctionCallExpression andExpr = new ScalarFunctionCallExpression(
+ BuiltinFunctions.getBuiltinFunctionInfo(AlgebricksBuiltinFunctions.AND));
- allPlans.add(pn);
- this.planIndexesArray.add(allPlans.size() - 1);
- this.cheapestPlanCost = totalCost;
- this.cheapestPlanIndex = allPlans.size() - 1;
+ for (i = 0; i < pairs.size(); i++) {
+ IOptimizableFuncExpr expr = exprs.get(pairs.get(i).getFirst());
+ andExpr.getArguments().add(new MutableObject<>(expr.getFuncExpr()));
+ }
+ return andExpr;
+ }
+
+ private void setSkipIndexAnnotationsForUnusedIndexes() {
+ for (int i = 0; i < IndexCostInfo.size(); i++) {
+ if (IndexCostInfo.get(i).second == -1.0) {
+ AbstractFunctionCallExpression afce = IndexCostInfo.get(i).third;
+ // this index has to be skipped, so find the corresponding expression
+ afce.putAnnotation(SkipSecondaryIndexSearchExpressionAnnotation
+ .newInstance(Collections.singleton(IndexCostInfo.get(i).first.getIndexName())));
+ }
}
}
- protected void costAndChooseIndexPlans(ILogicalOperator leafInput,
+ private void costAndChooseIndexPlans(ILogicalOperator leafInput,
Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs) throws AlgebricksException {
- // Skip indexes with selectivity greater than 0.1, add the SKIP_SECONDARY_INDEX annotation to its expression.
+ SelectOperator selOp;
double sel;
- int exprIndex;
+
+ List<Triple<Index, Double, AbstractFunctionCallExpression>> IndexCostInfo = new ArrayList<>();
for (Map.Entry<IAccessMethod, AccessMethodAnalysisContext> amEntry : analyzedAMs.entrySet()) {
AccessMethodAnalysisContext analysisCtx = amEntry.getValue();
Iterator<Map.Entry<Index, List<Pair<Integer, Integer>>>> indexIt =
@@ -350,24 +449,144 @@
while (indexIt.hasNext()) {
Map.Entry<Index, List<Pair<Integer, Integer>>> indexEntry = indexIt.next();
Index chosenIndex = indexEntry.getKey();
- exprIndex = indexEntry.getValue().get(0).getFirst();
- IOptimizableFuncExpr expr = exprs.get(exprIndex);
- AbstractFunctionCallExpression afce = expr.getFuncExpr();
+ if (chosenIndex.getIndexType().equals(DatasetConfig.IndexType.LENGTH_PARTITIONED_WORD_INVIX)
+ || chosenIndex.getIndexType().equals(DatasetConfig.IndexType.SINGLE_PARTITION_WORD_INVIX)
+ || chosenIndex.getIndexType().equals(DatasetConfig.IndexType.LENGTH_PARTITIONED_NGRAM_INVIX)
+ || chosenIndex.getIndexType().equals(DatasetConfig.IndexType.SINGLE_PARTITION_NGRAM_INVIX)) {
+ continue;
+ }
+ AbstractFunctionCallExpression afce = buildExpr(exprs, indexEntry.getValue());
PredicateCardinalityAnnotation selectivityAnnotation =
afce.getAnnotation(PredicateCardinalityAnnotation.class);
- if (joinEnum.findUseIndexHint(afce)) {
- buildIndexPlan(true);
- } else if (selectivityAnnotation != null) {
+ if (selectivityAnnotation != null) {
sel = selectivityAnnotation.getSelectivity();
- if (sel >= joinEnum.stats.SELECTIVITY_FOR_SECONDARY_INDEX_SELECTION) {
- afce.putAnnotation(SkipSecondaryIndexSearchExpressionAnnotation
- .newInstance(Collections.singleton(chosenIndex.getIndexName())));
+ } else {
+ if (leafInput.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
+ selOp = (SelectOperator) leafInput;
} else {
- buildIndexPlan(false);
+ selOp = new SelectOperator(new MutableObject<>(afce));
+ selOp.getInputs().add(new MutableObject<>(leafInput));
}
+ sel = joinEnum.getStatsHandle().findSelectivityForThisPredicate(selOp, afce, this.origCardinality);
+ }
+ IndexCostInfo.add(new Triple<>(chosenIndex, sel, afce));
+ }
+ }
+ this.IndexCostInfo = IndexCostInfo;
+ if (IndexCostInfo.size() > 0) {
+ buildIndexPlans();
+ }
+ setSkipIndexAnnotationsForUnusedIndexes();
+ }
+
+ private void buildIndexPlans() {
+ List<PlanNode> allPlans = joinEnum.getAllPlans();
+ ICost opCost, totalCost;
+ List<Triple<Index, Double, AbstractFunctionCallExpression>> mandatoryIndexesInfo = new ArrayList<>();
+ List<Triple<Index, Double, AbstractFunctionCallExpression>> optionalIndexesInfo = new ArrayList<>();
+ double sel = 1.0;
+ opCost = this.joinEnum.getCostHandle().zeroCost();
+ for (int i = 0; i < IndexCostInfo.size(); i++) {
+ if (joinEnum.findUseIndexHint(IndexCostInfo.get(i).third)) {
+ mandatoryIndexesInfo.add(IndexCostInfo.get(i));
+ } else {
+ optionalIndexesInfo.add(IndexCostInfo.get(i));
+ }
+ }
+
+ List<ICost> indexCosts = new ArrayList<>(); // these are the costs associated with the index only
+ // First cost all the mandatory indexes. These will be in the plan regardless of the cost
+ if (mandatoryIndexesInfo.size() > 0) {
+ for (int i = 0; i < mandatoryIndexesInfo.size(); i++) {
+ indexCosts.add(joinEnum.getCostMethodsHandle().costIndexScan(this, mandatoryIndexesInfo.get(i).second));
+ }
+
+ opCost = this.joinEnum.getCostHandle().zeroCost();
+
+ for (int i = 0; i < mandatoryIndexesInfo.size(); i++) {
+ opCost = opCost.costAdd(indexCosts.get(i)); // opCost will have all the index scan costs
+ sel *= mandatoryIndexesInfo.get(i).second; // assuming selectivities are independent for now
+ }
+
+ // Now add the data Scan cost.
+ ICost dataScanCost = joinEnum.getCostMethodsHandle().costIndexDataScan(this, sel);
+ opCost = opCost.costAdd(dataScanCost); // opCost now has the total cost of all the mandatory indexes + data costs.
+
+ }
+
+ ICost mandatoryIndexesCost = opCost; // This will be added at the end to the total cost irrespective of optimality.
+
+ // Now lets deal with the optional indexes. These are the ones without any hints on them.
+ List<ICost> dataCosts = new ArrayList<>(); // these are the costs associated with accessing the data records
+ indexCosts.clear();
+ if (optionalIndexesInfo.size() > 0) {
+ optionalIndexesInfo.sort(Comparator.comparingDouble(o -> o.second)); // sort on selectivity.
+
+ // find the costs using one index at a time first.
+
+ // sel is now the selectivity of all the previous mandatory indexes.
+ for (int i = 0; i < optionalIndexesInfo.size(); i++) {
+ indexCosts.add(joinEnum.getCostMethodsHandle().costIndexScan(this, optionalIndexesInfo.get(i).second)); // I0; I1; I2; ...
+ // Now get the cost of the datascans involved with the multiplied selectivity
+ // dataCost (0) will contain the dataScan cost with the first index
+ //dataCost (1) will contain the dataScan cost with the first index and the 2nd index and so on.
+ sel *= optionalIndexesInfo.get(i).second; // assuming selectivities are independent for now
+ dataCosts.add(joinEnum.getCostMethodsHandle().costIndexDataScan(this, sel)); // D0; D01; D012; ...
+ }
+
+ // At the of of the above loop, I0, I1, I2 ... have been computed
+ // Also D0, D01, D012 ... have been computed.
+
+ opCost = indexCosts.get(0).costAdd(dataCosts.get(0));
+ //opCost is now the cost of the first (and cheapest) optional index plus the corresponding data scan
+
+ //Intersect the first two and then the first three and so on.
+ //If the cost does not decrease, then stop
+
+ ICost newIdxCost = indexCosts.get(0); // I0
+ ICost currentCost;
+ for (int i = 1; i < optionalIndexesInfo.size(); i++) {
+ newIdxCost = newIdxCost.costAdd(indexCosts.get(i)); // I0 + I1; I0 + I1 + I2
+ currentCost = newIdxCost.costAdd(dataCosts.get(i)); // I0 + I1 + D01; I0 + I1 + I2 + D012
+ if (currentCost.costLT(opCost)) { // save this cost and try adding one more index
+ opCost = currentCost;
+ } else {
+ // set the selectivites of the indexes not picked to be -1.0, so we can set
+ // the skp index annotations correctly
+ for (int j = i; j < optionalIndexesInfo.size(); j++) {
+ optionalIndexesInfo.get(j).second = -1.0;
+ }
+ break; // can't get any cheaper.
}
}
}
+
+ // opCost is now the total cost of the indexes chosen along with the associated data scan cost.
+ if (opCost.costGT(this.cheapestPlanCost)) { // cheapest plan cost is the data scan cost.
+ for (int j = 0; j < optionalIndexesInfo.size(); j++) {
+ optionalIndexesInfo.get(j).second = -1.0; // remove all indexes from consideration.
+ }
+ }
+
+ totalCost = opCost.costAdd(mandatoryIndexesCost); // cost of all the indexes chosen
+ if (opCost.costLT(this.cheapestPlanCost) || mandatoryIndexesInfo.size() > 0) {
+ PlanNode pn = new PlanNode(allPlans.size(), joinEnum);
+ pn.setJoinNode(this);
+ pn.setDatasetName(getDatasetNames().get(0));
+ pn.setEmptyTupleSourceOp(this.correspondingEmptyTupleSourceOp);
+ pn.setLeftJoinIndex(this.jnArrayIndex);
+ pn.setRightJoinIndex(JoinNode.NO_JN);
+ pn.setLeftPlanIndex(PlanNode.NO_PLAN); // There ane no plans below this plan.
+ pn.setRightPlanIndex(PlanNode.NO_PLAN); // There ane no plans below this plan.
+ pn.setOpCost(totalCost);
+ pn.setScanMethod(PlanNode.ScanMethod.INDEX_SCAN);
+ pn.setTotalCost(totalCost);
+
+ allPlans.add(pn);
+ this.planIndexesArray.add(pn.allPlansIndex);
+ this.cheapestPlanCost = totalCost; // in the presence of mandatory indexes, this may not be the cheapest plan! But we have no choice!
+ this.cheapestPlanIndex = pn.allPlansIndex;
+ }
}
private SelectOperator copySelExprsAndSetTrue(List<ILogicalExpression> selExprs, List<SelectOperator> selOpers,
@@ -440,7 +659,7 @@
return changes;
}
- public void addIndexAccessPlans(ILogicalOperator leafInput) throws AlgebricksException {
+ protected void addIndexAccessPlans(ILogicalOperator leafInput) throws AlgebricksException {
IntroduceSelectAccessMethodRule tmp = new IntroduceSelectAccessMethodRule();
List<Pair<IAccessMethod, Index>> chosenIndexes = new ArrayList<>();
Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new TreeMap<>();
@@ -464,7 +683,7 @@
}
}
- protected int buildHashJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression hashJoinExpr,
+ private int buildHashJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression hashJoinExpr,
HashJoinExpressionAnnotation hintHashJoin) {
List<PlanNode> allPlans = joinEnum.allPlans;
PlanNode pn;
@@ -500,11 +719,11 @@
if (this.cheapestPlanIndex == PlanNode.NO_PLAN || totalCost.costLT(this.cheapestPlanCost)
|| hintHashJoin != null) {
pn = new PlanNode(allPlans.size(), joinEnum);
- pn.jn = this;
- pn.jnIndexes[0] = leftJn.jnArrayIndex;
- pn.jnIndexes[1] = rightJn.jnArrayIndex;
- pn.planIndexes[0] = leftPlan;
- pn.planIndexes[1] = rightPlan;
+ pn.setJoinNode(this);
+ pn.setLeftJoinIndex(leftJn.jnArrayIndex);
+ pn.setRightJoinIndex(rightJn.jnArrayIndex);
+ pn.setLeftPlanIndex(leftPlan);
+ pn.setRightPlanIndex(rightPlan);
pn.joinOp = PlanNode.JoinMethod.HYBRID_HASH_JOIN; // need to check that all the conditions have equality predicates ONLY.
pn.joinHint = hintHashJoin;
pn.side = HashJoinExpressionAnnotation.BuildSide.RIGHT;
@@ -522,7 +741,7 @@
return PlanNode.NO_PLAN;
}
- protected int buildBroadcastHashJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression hashJoinExpr,
+ private int buildBroadcastHashJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression hashJoinExpr,
BroadcastExpressionAnnotation hintBroadcastHashJoin) {
List<PlanNode> allPlans = joinEnum.allPlans;
PlanNode pn;
@@ -559,11 +778,11 @@
if (this.cheapestPlanIndex == PlanNode.NO_PLAN || totalCost.costLT(this.cheapestPlanCost)
|| hintBroadcastHashJoin != null) {
pn = new PlanNode(allPlans.size(), joinEnum);
- pn.jn = this;
- pn.jnIndexes[0] = leftJn.jnArrayIndex;
- pn.jnIndexes[1] = rightJn.jnArrayIndex;
- pn.planIndexes[0] = leftPlan;
- pn.planIndexes[1] = rightPlan;
+ pn.setJoinNode(this);
+ pn.setLeftJoinIndex(leftJn.jnArrayIndex);
+ pn.setRightJoinIndex(rightJn.jnArrayIndex);
+ pn.setLeftPlanIndex(leftPlan);
+ pn.setRightPlanIndex(rightPlan);
pn.joinOp = PlanNode.JoinMethod.BROADCAST_HASH_JOIN; // need to check that all the conditions have equality predicates ONLY.
pn.joinHint = hintBroadcastHashJoin;
pn.side = HashJoinExpressionAnnotation.BuildSide.RIGHT;
@@ -582,7 +801,7 @@
return PlanNode.NO_PLAN;
}
- protected int buildNLJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression nestedLoopJoinExpr,
+ private int buildNLJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression nestedLoopJoinExpr,
IndexedNLJoinExpressionAnnotation hintNLJoin) throws AlgebricksException {
// Build a nested loops plan, first check if it is possible
// left right order must be preserved and right side should be a single data set
@@ -612,11 +831,11 @@
if (this.cheapestPlanIndex == PlanNode.NO_PLAN || totalCost.costLT(this.cheapestPlanCost)
|| hintNLJoin != null) {
pn = new PlanNode(allPlans.size(), joinEnum);
- pn.jn = this;
- pn.jnIndexes[0] = leftJn.jnArrayIndex;
- pn.jnIndexes[1] = rightJn.jnArrayIndex;
- pn.planIndexes[0] = leftPlan;
- pn.planIndexes[1] = rightPlan;
+ pn.setJoinNode(this);
+ pn.setLeftJoinIndex(leftJn.jnArrayIndex);
+ pn.setRightJoinIndex(rightJn.jnArrayIndex);
+ pn.setLeftPlanIndex(leftPlan);
+ pn.setRightPlanIndex(rightPlan);
pn.joinOp = PlanNode.JoinMethod.INDEX_NESTED_LOOP_JOIN;
pn.joinHint = hintNLJoin;
pn.joinExpr = nestedLoopJoinExpr; // save it so can be used to add the NESTED annotation in getNewTree.
@@ -631,7 +850,7 @@
return PlanNode.NO_PLAN;
}
- protected int buildCPJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression hashJoinExpr,
+ private int buildCPJoinPlan(JoinNode leftJn, JoinNode rightJn, ILogicalExpression hashJoinExpr,
ILogicalExpression nestedLoopJoinExpr) {
// Now build a cartesian product nested loops plan
List<PlanNode> allPlans = joinEnum.allPlans;
@@ -668,11 +887,11 @@
totalCost = cpCost.costAdd(rightExchangeCost).costAdd(childCosts);
if (this.cheapestPlanIndex == PlanNode.NO_PLAN || totalCost.costLT(this.cheapestPlanCost)) {
pn = new PlanNode(allPlans.size(), joinEnum);
- pn.jn = this;
- pn.jnIndexes[0] = leftJn.jnArrayIndex;
- pn.jnIndexes[1] = rightJn.jnArrayIndex;
- pn.planIndexes[0] = leftPlan;
- pn.planIndexes[1] = rightPlan;
+ pn.setJoinNode(this);
+ pn.setLeftJoinIndex(leftJn.jnArrayIndex);
+ pn.setRightJoinIndex(rightJn.jnArrayIndex);
+ pn.setLeftPlanIndex(leftPlan);
+ pn.setRightPlanIndex(rightPlan);
pn.joinOp = PlanNode.JoinMethod.CARTESIAN_PRODUCT_JOIN;
pn.joinExpr = Objects.requireNonNullElse(cpJoinExpr, ConstantExpression.TRUE);
pn.opCost = cpCost;
@@ -1000,7 +1219,7 @@
return sb.toString();
}
- public void printCostOfAllPlans(StringBuilder sb) {
+ protected void printCostOfAllPlans(StringBuilder sb) {
List<PlanNode> allPlans = joinEnum.allPlans;
ICost minCost = joinEnum.getCostHandle().maxCost();
for (int planIndex : planIndexesArray) {
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java
index 1e91347..7ccd435 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java
@@ -29,33 +29,33 @@
public class PlanNode {
- public static int NO_PLAN = -1;
+ protected static int NO_PLAN = -1;
private final JoinEnum joinEnum;
- int allPlansIndex;
- int[] planIndexes;
- int[] jnIndexes;
- JoinNode jn;
- String datasetName;
- ICost opCost;
- ICost totalCost;
- ICost leftExchangeCost;
- ICost rightExchangeCost;
- JoinMethod joinOp;
- IExpressionAnnotation joinHint;
+ protected int allPlansIndex;
+ protected int[] planIndexes;
+ protected int[] jnIndexes;
+ protected JoinNode jn;
+ protected String datasetName;
+ protected ICost opCost;
+ protected ICost totalCost;
+ protected ICost leftExchangeCost;
+ protected ICost rightExchangeCost;
+ protected JoinMethod joinOp;
+ protected IExpressionAnnotation joinHint;
// Used to indicate which side to build for HJ and which side to broadcast for BHJ.
- HashJoinExpressionAnnotation.BuildSide side;
- ScanMethod scanOp;
- ILogicalExpression joinExpr;
- DataSourceScanOperator correspondingDataSourceScanOp;
- EmptyTupleSourceOperator correspondingEmptyTupleSourceOp;
+ protected HashJoinExpressionAnnotation.BuildSide side;
+ protected ScanMethod scanOp;
+ protected ILogicalExpression joinExpr;
+ private DataSourceScanOperator correspondingDataSourceScanOp;
+ protected EmptyTupleSourceOperator correspondingEmptyTupleSourceOp;
public enum ScanMethod {
INDEX_SCAN,
TABLE_SCAN
}
- public enum JoinMethod {
+ protected enum JoinMethod {
HYBRID_HASH_JOIN,
BROADCAST_HASH_JOIN,
INDEX_NESTED_LOOP_JOIN,
@@ -73,14 +73,10 @@
return allPlansIndex;
}
- public int[] getPlanIndexes() {
+ private int[] getPlanIndexes() {
return planIndexes;
}
- public int getLeftPlanIndex() {
- return planIndexes[0];
- }
-
public PlanNode getLeftPlanNode() {
if (planIndexes[0] == NO_PLAN) {
return null;
@@ -95,47 +91,51 @@
return joinEnum.allPlans.get(planIndexes[1]);
}
- public JoinNode getJoinNode() {
+ protected JoinNode getJoinNode() {
return jn;
}
- public void setJoinNode(JoinNode jn) {
+ protected void setJoinNode(JoinNode jn) {
this.jn = jn;
}
- public int getRightPlanIndex() {
- return planIndexes[1];
- }
-
- public void setRightPlanIndex(int index) {
- this.planIndexes[1] = index;
- }
-
public int getLeftJoinIndex() {
return jnIndexes[0];
}
- public void setLeftPlanIndex(int index) {
- this.planIndexes[0] = index;
- }
-
- public void setLeftJoinIndex(int index) {
+ protected void setLeftJoinIndex(int index) {
this.jnIndexes[0] = index;
}
- public void setRightJoinIndex(int index) {
- this.jnIndexes[1] = index;
- }
-
public int getRightJoinIndex() {
return jnIndexes[1];
}
+ protected void setRightJoinIndex(int index) {
+ this.jnIndexes[1] = index;
+ }
+
+ protected int getLeftPlanIndex() {
+ return planIndexes[0];
+ }
+
+ protected void setLeftPlanIndex(int index) {
+ this.planIndexes[0] = index;
+ }
+
+ protected int getRightPlanIndex() {
+ return planIndexes[1];
+ }
+
+ protected void setRightPlanIndex(int index) {
+ this.planIndexes[1] = index;
+ }
+
public boolean IsScanNode() {
return getLeftPlanIndex() == NO_PLAN && getRightPlanIndex() == NO_PLAN;
}
- public boolean IsJoinNode() {
+ protected boolean IsJoinNode() {
return getLeftPlanIndex() != NO_PLAN && getRightPlanIndex() != NO_PLAN;
}
@@ -152,23 +152,23 @@
return new Pair<>("", "");
}
- public String getDatasetName() {
+ private String getDatasetName() {
return datasetName;
}
- public void setDatasetName(String dsName) {
+ protected void setDatasetName(String dsName) {
this.datasetName = dsName;
}
- public DataSourceScanOperator getDataSourceScanOp() {
+ private DataSourceScanOperator getDataSourceScanOp() {
return correspondingDataSourceScanOp; // This applies only to singleDataSetPlans
}
- public EmptyTupleSourceOperator getEmptyTupleSourceOp() {
+ protected EmptyTupleSourceOperator getEmptyTupleSourceOp() {
return correspondingEmptyTupleSourceOp; // This applies only to singleDataSetPlans
}
- public void setEmptyTupleSourceOp(EmptyTupleSourceOperator emptyTupleSourceOp) {
+ protected void setEmptyTupleSourceOp(EmptyTupleSourceOperator emptyTupleSourceOp) {
this.correspondingEmptyTupleSourceOp = emptyTupleSourceOp; // This applies only to singleDataSetPlans
}
@@ -176,11 +176,11 @@
return opCost;
}
- public void setOpCost(ICost cost) {
+ protected void setOpCost(ICost cost) {
this.opCost = cost;
}
- public double computeOpCost() {
+ protected double computeOpCost() {
return opCost.computeTotalCost();
}
@@ -188,7 +188,7 @@
return totalCost;
}
- public void setTotalCost(ICost tc) {
+ protected void setTotalCost(ICost tc) {
this.totalCost = tc;
}
@@ -200,7 +200,7 @@
return rightExchangeCost;
}
- public double computeTotalCost() {
+ protected double computeTotalCost() {
return totalCost.computeTotalCost();
}
@@ -208,11 +208,11 @@
return scanOp;
}
- public void setScanMethod(ScanMethod sm) {
+ protected void setScanMethod(ScanMethod sm) {
this.scanOp = sm;
}
- public JoinMethod getJoinOp() {
+ protected JoinMethod getJoinOp() {
return joinOp;
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java
index b3c4876..785d56b 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/Stats.java
@@ -20,13 +20,23 @@
package org.apache.asterix.optimizer.rules.cbo;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.compiler.provider.IRuleSetFactory;
import org.apache.asterix.metadata.declared.DataSource;
import org.apache.asterix.metadata.declared.DataSourceId;
import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.metadata.declared.SampleDataSource;
import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.om.base.AInt64;
+import org.apache.asterix.om.base.IAObject;
+import org.apache.asterix.om.functions.BuiltinFunctionInfo;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.optimizer.base.AnalysisUtil;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.commons.lang3.mutable.MutableObject;
import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
@@ -35,29 +45,34 @@
import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AggregateFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
import org.apache.hyracks.algebricks.core.algebra.expressions.JoinProductivityAnnotation;
import org.apache.hyracks.algebricks.core.algebra.expressions.PredicateCardinalityAnnotation;
import org.apache.hyracks.algebricks.core.algebra.functions.AlgebricksBuiltinFunctions;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AggregateOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
import org.apache.hyracks.algebricks.core.algebra.operators.logical.SubplanOperator;
+import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil;
+import org.apache.hyracks.algebricks.core.algebra.util.OperatorPropertiesUtil;
import org.apache.hyracks.api.exceptions.ErrorCode;
import org.apache.hyracks.api.exceptions.IWarningCollector;
import org.apache.hyracks.api.exceptions.Warning;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
public class Stats {
-
- public double SELECTIVITY_FOR_SECONDARY_INDEX_SELECTION = 0.1;
-
- protected IOptimizationContext optCtx;
- protected JoinEnum joinEnum;
+ private static final Logger LOGGER = LogManager.getLogger();
+ private final IOptimizationContext optCtx;
+ private final JoinEnum joinEnum;
public Stats(IOptimizationContext context, JoinEnum joinE) {
optCtx = context;
joinEnum = joinE;
}
- public DataverseName findDataverseName(DataSourceScanOperator scanOp) {
+ protected DataverseName findDataverseName(DataSourceScanOperator scanOp) {
if (scanOp == null) {
// this should rarely happen (IN lists may cause this)
return null;
@@ -66,7 +81,7 @@
return dsid.getDataverseName();
}
- public Index findSampleIndex(DataSourceScanOperator scanOp, IOptimizationContext context)
+ protected Index findSampleIndex(DataSourceScanOperator scanOp, IOptimizationContext context)
throws AlgebricksException {
DataverseName dataverseName = findDataverseName(scanOp);
DataSource ds = (DataSource) scanOp.getDataSource();
@@ -130,7 +145,7 @@
// The expression we get may not be a base condition. It could be comprised of ors and ands and nots. So have to
//recursively find the overall selectivity.
- protected double getSelectivityFromAnnotation(AbstractFunctionCallExpression afcExpr, boolean join)
+ private double getSelectivityFromAnnotation(AbstractFunctionCallExpression afcExpr, boolean join)
throws AlgebricksException {
double sel = 1.0;
@@ -166,7 +181,7 @@
}
}
- double s = 1.0;
+ double s;
PredicateCardinalityAnnotation pca = afcExpr.getAnnotation(PredicateCardinalityAnnotation.class);
if (pca != null) {
s = pca.getSelectivity();
@@ -192,7 +207,8 @@
return sel;
}
- public double getSelectivityFromAnnotationMain(ILogicalExpression leExpr, boolean join) throws AlgebricksException {
+ protected double getSelectivityFromAnnotationMain(ILogicalExpression leExpr, boolean join)
+ throws AlgebricksException {
double sel = 1.0;
if (leExpr.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
@@ -225,7 +241,7 @@
return sel;
}
- protected double getSelectivity(SubplanOperator subplanOp) throws AlgebricksException {
+ private double getSelectivity(SubplanOperator subplanOp) throws AlgebricksException {
double sel = 1.0; // safe to return 1 if there is no annotation
//ILogicalOperator op = subplanOp;
ILogicalOperator op = subplanOp.getNestedPlans().get(0).getRoots().get(0).getValue();
@@ -242,4 +258,229 @@
}
return sel;
}
+
+ private int countOps(ILogicalOperator op, LogicalOperatorTag tag) {
+ int count = 0;
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(tag)) {
+ count++;
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ return count;
+ }
+
+ private SubplanOperator findSubplanWithExpr(ILogicalOperator op, ILogicalExpression exp)
+ throws AlgebricksException {
+ /*private final */ ContainsExpressionVisitor visitor = new ContainsExpressionVisitor();
+ SubplanOperator subOp;
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
+ subOp = (SubplanOperator) op;
+ ILogicalOperator nextOp = subOp.getNestedPlans().get(0).getRoots().get(0).getValue();
+
+ while (nextOp != null) {
+ visitor.setExpression(exp);
+ if (nextOp.acceptExpressionTransform(visitor)) {
+ return subOp;
+ }
+
+ if (nextOp.getInputs().isEmpty()) {
+ break;
+ }
+ nextOp = nextOp.getInputs().get(0).getValue();
+ }
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ return null;
+ }
+
+ private List<ILogicalExpression> storeSubplanSelectsAndMakeThemTrue(ILogicalOperator op) {
+ List<ILogicalExpression> selExprs = new ArrayList<>();
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
+ if (op.getInputs().get(0).getValue().getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
+ SelectOperator selOp = (SelectOperator) op;
+ selExprs.add(selOp.getCondition().getValue());
+ selOp.getCondition().setValue(ConstantExpression.TRUE);
+ }
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ return selExprs;
+ }
+
+ private void restoreAllSubplanSelects(ILogicalOperator op, List<ILogicalExpression> selExprs) {
+ int i = 0;
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
+ if (op.getInputs().get(0).getValue().getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
+ SelectOperator selOp = (SelectOperator) op;
+ selOp.getCondition().setValue(selExprs.get(i));
+ i++;
+ }
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ }
+
+ // For the SubOp subplan, leave the selection condition the same but all other selects and subsplan selects should be marked true
+ private List<ILogicalExpression> storeSubplanSelectsAndMakeThemTrue(ILogicalOperator op, SubplanOperator subOp) {
+ List<ILogicalExpression> selExprs = new ArrayList<>();
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
+ ILogicalOperator op2 = op.getInputs().get(0).getValue();
+ if (op2.getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
+ SubplanOperator subOp2 = (SubplanOperator) op2;
+ if (subOp2 != subOp) {
+ SelectOperator selOp = (SelectOperator) op;
+ selExprs.add(selOp.getCondition().getValue());
+ selOp.getCondition().setValue(ConstantExpression.TRUE);
+ } // else leave expression as is.
+ } else { // a non subplan select
+ SelectOperator selOp = (SelectOperator) op;
+ selExprs.add(selOp.getCondition().getValue());
+ selOp.getCondition().setValue(ConstantExpression.TRUE);
+ }
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ return selExprs;
+ }
+
+ private void restoreAllSubplanSelectConditions(ILogicalOperator op, List<ILogicalExpression> selExprs,
+ SubplanOperator subOp) {
+ int i = 0;
+ while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
+ if (op.getOperatorTag().equals(LogicalOperatorTag.SELECT)) {
+ ILogicalOperator op2 = op.getInputs().get(0).getValue();
+ if (op2.getOperatorTag().equals(LogicalOperatorTag.SUBPLAN)) {
+ SubplanOperator subOp2 = (SubplanOperator) op2;
+ if (subOp2 != subOp) {
+ SelectOperator selOp = (SelectOperator) op;
+ selOp.getCondition().setValue(selExprs.get(i));
+ i++;
+ }
+ } else { // a non subplan select
+ SelectOperator selOp = (SelectOperator) op;
+ selOp.getCondition().setValue(selExprs.get(i));
+ }
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ }
+
+ protected double findSelectivityForThisPredicate(SelectOperator selOp, AbstractFunctionCallExpression exp,
+ double datasetCard) throws AlgebricksException {
+ // replace the SelOp.condition with the new exp and replace it at the end
+ // The Selop here is the start of the leafInput.
+
+ ILogicalOperator parent = joinEnum.findDataSourceScanOperatorParent(selOp);
+ DataSourceScanOperator scanOp = (DataSourceScanOperator) parent.getInputs().get(0).getValue();
+
+ if (scanOp == null) {
+ return 1.0; // what happens to the cards and sizes then? this may happen in case of in lists
+ }
+
+ Index index = findSampleIndex(scanOp, optCtx);
+ if (index == null) {
+ return 1.0;
+ }
+
+ Index.SampleIndexDetails idxDetails = (Index.SampleIndexDetails) index.getIndexDetails();
+ double origDatasetCard = idxDetails.getSourceCardinality();
+ // origDatasetCard must be equal to datasetCard. So we do not need datasetCard passed in here. VIJAY check if
+ // this parameter can be removed.
+ double sampleCard = Math.min(idxDetails.getSampleCardinalityTarget(), origDatasetCard);
+ if (sampleCard == 0) {
+ sampleCard = 1;
+ IWarningCollector warningCollector = optCtx.getWarningCollector();
+ if (warningCollector.shouldWarn()) {
+ warningCollector.warn(Warning.of(scanOp.getSourceLocation(),
+ org.apache.asterix.common.exceptions.ErrorCode.SAMPLE_HAS_ZERO_ROWS));
+ }
+ }
+
+ // replace the dataScanSourceOperator with the sampling source
+ SampleDataSource sampledatasource = joinEnum.getSampleDataSource(scanOp);
+ DataSourceScanOperator deepCopyofScan =
+ (DataSourceScanOperator) OperatorManipulationUtil.bottomUpCopyOperators(scanOp);
+ deepCopyofScan.setDataSource(sampledatasource);
+
+ int numSubplans = countOps(selOp, LogicalOperatorTag.SUBPLAN);
+
+ List<List<IAObject>> result;
+
+ // insert this in place of the scandatasourceOp.
+ parent.getInputs().get(0).setValue(deepCopyofScan);
+ if (numSubplans == 0) { // just switch the predicates; the simplest case. There should be no other case if subplans were canonical
+ ILogicalExpression saveExprs = selOp.getCondition().getValue();
+ selOp.getCondition().setValue(exp);
+ result = runSamplingQuery(optCtx, selOp);
+ selOp.getCondition().setValue(saveExprs);
+ } else {
+ int numSelects = countOps(selOp, LogicalOperatorTag.SELECT);
+ int nonSubplanSelects = numSelects - numSubplans;
+
+ if (numSubplans == 1 && nonSubplanSelects == 0) {
+ result = runSamplingQuery(optCtx, selOp); // no need to switch anything
+ } else { // the painful part; have to find where exp that is passed in is coming from. >= 1 and >= 1 case
+ // Assumption is that there is exaclty one select condition above each subplan.
+ // This was ensured before this routine is called
+ SubplanOperator subOp = findSubplanWithExpr(selOp, exp);
+ if (subOp == null) { // the exp is not coming from a subplan
+ List<ILogicalExpression> selExprs;
+ selExprs = storeSubplanSelectsAndMakeThemTrue(selOp); // all these will be marked true and will be resorted later.
+ result = runSamplingQuery(optCtx, selOp);
+ restoreAllSubplanSelects(selOp, selExprs);
+ } else { // found the matching subPlan oper. Only keep this predicate and make all others true and then restore them.
+ List<ILogicalExpression> selExprs;
+ selExprs = storeSubplanSelectsAndMakeThemTrue(selOp, subOp); // all these will be marked true and will be resorted later.
+ result = runSamplingQuery(optCtx, selOp);
+ restoreAllSubplanSelectConditions(selOp, selExprs, subOp);
+ }
+ }
+ }
+ // switch the scanOp back
+ parent.getInputs().get(0).setValue(scanOp);
+
+ double predicateCardinality = (double) ((AInt64) result.get(0).get(0)).getLongValue();
+ if (predicateCardinality == 0.0) {
+ predicateCardinality = 0.0001 * idxDetails.getSampleCardinalityTarget();
+ }
+ double sel = (double) predicateCardinality / sampleCard;
+ return sel;
+ }
+
+ protected List<List<IAObject>> runSamplingQuery(IOptimizationContext ctx, ILogicalOperator logOp)
+ throws AlgebricksException {
+ LOGGER.info("***running sample query***");
+
+ IOptimizationContext newCtx = ctx.getOptimizationContextFactory().cloneOptimizationContext(ctx);
+
+ ILogicalOperator newScanOp = OperatorManipulationUtil.bottomUpCopyOperators(logOp);
+
+ List<Mutable<ILogicalExpression>> aggFunArgs = new ArrayList<>(1);
+ aggFunArgs.add(new MutableObject<>(ConstantExpression.TRUE));
+ BuiltinFunctionInfo countFn = BuiltinFunctions.getBuiltinFunctionInfo(BuiltinFunctions.COUNT);
+ AggregateFunctionCallExpression aggExpr = new AggregateFunctionCallExpression(countFn, false, aggFunArgs);
+
+ List<Mutable<ILogicalExpression>> aggExprList = new ArrayList<>(1);
+ aggExprList.add(new MutableObject<>(aggExpr));
+
+ List<LogicalVariable> aggVarList = new ArrayList<>(1);
+ LogicalVariable aggVar = newCtx.newVar();
+ aggVarList.add(aggVar);
+
+ AggregateOperator newAggOp = new AggregateOperator(aggVarList, aggExprList);
+ newAggOp.getInputs().add(new MutableObject<>(newScanOp));
+
+ Mutable<ILogicalOperator> newAggOpRef = new MutableObject<>(newAggOp);
+
+ OperatorPropertiesUtil.typeOpRec(newAggOpRef, newCtx);
+ LOGGER.info("***returning from sample query***");
+
+ return AnalysisUtil.runQuery(newAggOpRef, Arrays.asList(aggVar), newCtx, IRuleSetFactory.RuleSetKind.SAMPLING);
+ }
}
diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/AnalyzingTestExecutor.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/AnalyzingTestExecutor.java
index 485e359..2658804 100644
--- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/AnalyzingTestExecutor.java
+++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/common/AnalyzingTestExecutor.java
@@ -68,6 +68,7 @@
analyzeStmt.append(dv);
}
analyzeStmt.append(ds);
+ analyzeStmt.append(" WITH {\"sample-seed\": \"1000\"}");
analyzeStmt.append(";");
InputStream resultStream = executeQueryService(analyzeStmt.toString(), getQueryServiceUri(SQLPP),
TestCaseContext.OutputFormat.CLEAN_JSON);
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-indexes/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-indexes/query1.plan
new file mode 100644
index 0000000..498ee33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-indexes/query1.plan
@@ -0,0 +1,21 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (test.KSI) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-indexes/query2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-indexes/query2.plan
new file mode 100644
index 0000000..498ee33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-indexes/query2.plan
@@ -0,0 +1,21 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (test.KSI) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/query7.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/query7.plan
new file mode 100644
index 0000000..9e577d4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/query7.plan
@@ -0,0 +1,22 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestDataverse.Dataset1) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-1/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-1/query1.plan
new file mode 100644
index 0000000..1abd71a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-1/query1.plan
@@ -0,0 +1,21 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-2/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-2/query1.plan
new file mode 100644
index 0000000..1abd71a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-2/query1.plan
@@ -0,0 +1,21 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-3/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-3/query1.plan
new file mode 100644
index 0000000..c5a8718
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-3/query1.plan
@@ -0,0 +1,22 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-3/query2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-3/query2.plan
new file mode 100644
index 0000000..c5a8718
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/multiple-quantifiers/use-case-3/query2.plan
@@ -0,0 +1,22 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-1/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-1/query1.plan
new file mode 100644
index 0000000..1abd71a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-1/query1.plan
@@ -0,0 +1,21 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-2/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-2/query1.plan
new file mode 100644
index 0000000..1abd71a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-2/query1.plan
@@ -0,0 +1,21 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-3/query1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-3/query1.plan
new file mode 100644
index 0000000..c5a8718
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-3/query1.plan
@@ -0,0 +1,22 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-3/query2.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-3/query2.plan
new file mode 100644
index 0000000..c5a8718
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/array-index/select-quantified-queries/use-case-3/query2.plan
@@ -0,0 +1,22 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SUBPLAN |PARTITIONED|
+ {
+ -- AGGREGATE |LOCAL|
+ -- STREAM_SELECT |LOCAL|
+ -- ASSIGN |LOCAL|
+ -- UNNEST |LOCAL|
+ -- NESTED_TUPLE_SOURCE |LOCAL|
+ }
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (TestYelp.YelpCheckin) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-10.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-10.plan
new file mode 100644
index 0000000..83ba8b8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-10.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$20(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-11.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-11.plan
new file mode 100644
index 0000000..9643deb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-11.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$20(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-12.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-12.plan
new file mode 100644
index 0000000..13375cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-12.plan
@@ -0,0 +1,37 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- INTERSECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$29(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$34(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_5k_10k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-13.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-13.plan
new file mode 100644
index 0000000..83ba8b8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-13.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$20(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-14.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-14.plan
new file mode 100644
index 0000000..6eb942d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-14.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$20(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-15.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-15.plan
new file mode 100644
index 0000000..725e81e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-15.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$28(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan
new file mode 100644
index 0000000..00ba0d7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-17.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-17.plan
new file mode 100644
index 0000000..6e732ed
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-17.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$29(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-3.plan
new file mode 100644
index 0000000..9643deb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-3.plan
@@ -0,0 +1,19 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$20(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-4.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-4.plan
new file mode 100644
index 0000000..cf09754
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-4.plan
@@ -0,0 +1,37 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- INTERSECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$28(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$32(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-5.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-5.plan
new file mode 100644
index 0000000..13375cb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-5.plan
@@ -0,0 +1,37 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- INTERSECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$29(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$34(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_5k_10k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-7.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-7.plan
index 86e54c9..00ba0d7 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-7.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-7.plan
@@ -1,12 +1,19 @@
-- DISTRIBUTE_RESULT |PARTITIONED|
- -- SORT_MERGE_EXCHANGE [$$23(ASC) ] |PARTITIONED|
- -- STABLE_SORT [$$23(ASC)] |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- STREAM_SELECT |PARTITIONED|
-- ASSIGN |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- DATASOURCE_SCAN (test.tenk) |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-8.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-8.plan
new file mode 100644
index 0000000..7e83ccb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-8.plan
@@ -0,0 +1,30 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- INTERSECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$36(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_2k_5k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-9.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-9.plan
new file mode 100644
index 0000000..7e83ccb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-9.plan
@@ -0,0 +1,30 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$24(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- INTERSECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_1k_2k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$36(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_2k_5k) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.1.plan
index 65df3c2..d44143c 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.1.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.1.plan
@@ -4,8 +4,8 @@
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
-- AGGREGATE |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- HYBRID_HASH_JOIN [$$130][$$129] |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$130] |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$137][$$136] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$137] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- STREAM_SELECT |PARTITIONED|
-- ASSIGN |PARTITIONED|
@@ -14,49 +14,31 @@
-- DATASOURCE_SCAN (test.region) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$129] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$136] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- HYBRID_HASH_JOIN [$$127, $$131][$$128, $$132] |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$127, $$131] |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$124][$$123] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$124] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ASSIGN |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- DATASOURCE_SCAN (test.lineitem) |PARTITIONED|
+ -- DATASOURCE_SCAN (test.nation) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$128, $$132] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$123] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- HYBRID_HASH_JOIN [$$126][$$125] |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$126] |PARTITIONED|
- -- STREAM_PROJECT |PARTITIONED|
- -- STREAM_SELECT |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 [$$125] |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$134, $$122][$$135, $$123] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$134, $$122] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- HYBRID_HASH_JOIN [$$117][$$116] |PARTITIONED|
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$139][$$138] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$139] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- HYBRID_HASH_JOIN [$$117][$$115] |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$117] |PARTITIONED|
- -- STREAM_PROJECT |PARTITIONED|
- -- ASSIGN |PARTITIONED|
- -- STREAM_PROJECT |PARTITIONED|
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- DATASOURCE_SCAN (test.nation) |PARTITIONED|
- -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- EMPTY_TUPLE_SOURCE |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$115] |PARTITIONED|
+ -- HYBRID_HASH_JOIN [$$132][$$133] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$132] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ASSIGN |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
@@ -64,11 +46,29 @@
-- DATASOURCE_SCAN (test.customer) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
- -- HASH_PARTITION_EXCHANGE [$$116] |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$133] |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |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 [$$138] |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ASSIGN |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- DATASOURCE_SCAN (test.supplier) |PARTITIONED|
+ -- DATASOURCE_SCAN (test.lineitem) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- HASH_PARTITION_EXCHANGE [$$135, $$123] |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (test.supplier) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-edit-distance-check.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-edit-distance-check.plan
new file mode 100644
index 0000000..334be33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-edit-distance-check.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$19(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-edit-distance.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-edit-distance.plan
new file mode 100644
index 0000000..334be33
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-edit-distance.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$19(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-fuzzyeq-edit-distance.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-fuzzyeq-edit-distance.plan
new file mode 100644
index 0000000..0589004
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-fuzzyeq-edit-distance.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$18(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-fuzzyeq-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-fuzzyeq-jaccard.plan
new file mode 100644
index 0000000..b415aa0
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-fuzzyeq-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-jaccard-check.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-jaccard-check.plan
new file mode 100644
index 0000000..76c3b3b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-jaccard-check.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-jaccard.plan
new file mode 100644
index 0000000..76c3b3b
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ngram-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance-check.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance-check.plan
new file mode 100644
index 0000000..971ae76
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance-check.plan
@@ -0,0 +1,16 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$18(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$18(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$22(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance-check_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance-check_ps.plan
new file mode 100644
index 0000000..a88b1e8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance-check_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$18(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$18(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$22(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$22(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance.plan
new file mode 100644
index 0000000..971ae76
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance.plan
@@ -0,0 +1,16 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$18(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$18(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$22(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance_ps.plan
new file mode 100644
index 0000000..a88b1e8
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-edit-distance_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$18(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$18(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$22(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$22(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-edit-distance.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-edit-distance.plan
new file mode 100644
index 0000000..ad32edd
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-edit-distance.plan
@@ -0,0 +1,16 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$17(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$17(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-edit-distance_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-edit-distance_ps.plan
new file mode 100644
index 0000000..7a151d5
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-edit-distance_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$17(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$17(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-jaccard.plan
new file mode 100644
index 0000000..a9465ae
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-fuzzyeq-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$19(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-jaccard-check.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-jaccard-check.plan
new file mode 100644
index 0000000..56b3d06
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-jaccard-check.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-jaccard.plan
new file mode 100644
index 0000000..56b3d06
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/olist-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-fuzzyeq-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-fuzzyeq-jaccard.plan
new file mode 100644
index 0000000..a9465ae
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-fuzzyeq-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$19(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-jaccard-check.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-jaccard-check.plan
new file mode 100644
index 0000000..56b3d06
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-jaccard-check.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-jaccard.plan
new file mode 100644
index 0000000..56b3d06
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/ulist-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-fuzzyeq-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-fuzzyeq-jaccard.plan
new file mode 100644
index 0000000..f4a3522
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-fuzzyeq-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.keyword_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-jaccard-check.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-jaccard-check.plan
new file mode 100644
index 0000000..043f7d4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-jaccard-check.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.keyword_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-jaccard.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-jaccard.plan
new file mode 100644
index 0000000..043f7d4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-basic/word-jaccard.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$21(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.keyword_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let-panic-nopanic_01.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let-panic-nopanic_01.plan
new file mode 100644
index 0000000..6d1d661
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let-panic-nopanic_01.plan
@@ -0,0 +1,15 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$45(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let-panic-nopanic_02.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let-panic-nopanic_02.plan
new file mode 100644
index 0000000..6d1d661
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let-panic-nopanic_02.plan
@@ -0,0 +1,15 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$45(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let.plan
new file mode 100644
index 0000000..f1cac23
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-let.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$30(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-substring.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-substring.plan
new file mode 100644
index 0000000..2b26d45
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-edit-distance-check-substring.plan
@@ -0,0 +1,16 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-jaccard-check-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-jaccard-check-let.plan
new file mode 100644
index 0000000..06ac713
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-jaccard-check-let.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$32(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-jaccard-check-multi-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-jaccard-check-multi-let.plan
new file mode 100644
index 0000000..1d0f0a4
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ngram-jaccard-check-multi-let.plan
@@ -0,0 +1,17 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$58(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.ngram_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-edit-distance-check-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-edit-distance-check-let.plan
new file mode 100644
index 0000000..5b54be6
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-edit-distance-check-let.plan
@@ -0,0 +1,16 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$29(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$29(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$33(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-edit-distance-check-let_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-edit-distance-check-let_ps.plan
new file mode 100644
index 0000000..e8039ef
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-edit-distance-check-let_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$29(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$29(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$33(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$33(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-jaccard-check-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-jaccard-check-let.plan
new file mode 100644
index 0000000..c597083
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/olist-jaccard-check-let.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ulist-jaccard-check-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ulist-jaccard-check-let.plan
new file mode 100644
index 0000000..c597083
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/ulist-jaccard-check-let.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/word-jaccard-check-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/word-jaccard-check-let.plan
new file mode 100644
index 0000000..c30299a
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/word-jaccard-check-let.plan
@@ -0,0 +1,13 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$32(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.keyword_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/word-jaccard-check-multi-let.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/word-jaccard-check-multi-let.plan
new file mode 100644
index 0000000..99e1895
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/inverted-index-complex/word-jaccard-check-multi-let.plan
@@ -0,0 +1,17 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.DBLP.DBLP) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$58(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.DBLP.keyword_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-edit-distance-check_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-edit-distance-check_ps.plan
new file mode 100644
index 0000000..7597fd2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-edit-distance-check_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$20(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-edit-distance_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-edit-distance_ps.plan
new file mode 100644
index 0000000..7597fd2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-edit-distance_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$20(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$20(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$25(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-fuzzyeq-edit-distance_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-fuzzyeq-edit-distance_ps.plan
new file mode 100644
index 0000000..6e8c23d
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-basic/olist-fuzzyeq-edit-distance_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$19(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$19(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$24(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-complex/olist-edit-distance-check-let_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-complex/olist-edit-distance-check-let_ps.plan
new file mode 100644
index 0000000..5c43154
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/nested-index/inverted-index-complex/olist-edit-distance-check-let_ps.plan
@@ -0,0 +1,38 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- RANGE_PARTITION_EXCHANGE [$$31(ASC)] |PARTITIONED|
+ -- FORWARD |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$36(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |UNPARTITIONED|
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ -- AGGREGATE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- REPLICATE |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (test.Customers.Customers) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$36(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- LENGTH_PARTITIONED_INVERTED_INDEX_SEARCH (test.Customers.interests_index) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/query-ASTERIXDB-2700.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/query-ASTERIXDB-2700.plan
new file mode 100644
index 0000000..5c72fa2
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/query-ASTERIXDB-2700.plan
@@ -0,0 +1,28 @@
+-- DISTRIBUTE_RESULT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (bigfun.GleambookMessagesComposite.GleambookMessagesComposite) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STABLE_SORT [$$58(ASC), $$59(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- BTREE_SEARCH (bigfun.GleambookMessagesComposite.authorIdIx) |PARTITIONED|
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$48(ASC) ] |PARTITIONED|
+ -- STABLE_SORT [$$48(ASC)] |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- STREAM_SELECT |PARTITIONED|
+ -- ASSIGN |PARTITIONED|
+ -- STREAM_PROJECT |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- DATASOURCE_SCAN (bigfun.GleambookUsersComposite) |PARTITIONED|
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan
index e7f6361..5994520 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan
@@ -1,18 +1,18 @@
-distribute result [$$51] [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+distribute result [$$51] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ project ([$$51]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- SORT_MERGE_EXCHANGE [$$58(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- STABLE_SORT [$$58(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$55, $$58)) [cardinality: 2.1, op-cost: 2000000.0, total-cost: 1.1E7]
+ join (eq($$55, $$58)) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 1.1E7]
-- HYBRID_HASH_JOIN [$$58][$$55] |PARTITIONED|
exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan
index 554d42f..453c83d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan
@@ -1,62 +1,62 @@
-distribute result [$$48] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+distribute result [$$51] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$48]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ project ([$$51]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$48] <- [{"n_nationkey": $$55, "s_nationkey": $$53, "c_nationkey": $$52}] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- SORT_MERGE_EXCHANGE [$$55(ASC), $$53(ASC), $$52(ASC) ] |PARTITIONED|
- order (ASC, $$55) (ASC, $$53) (ASC, $$52) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- STABLE_SORT [$$55(ASC), $$53(ASC), $$52(ASC)] |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$58(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
+ order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- STABLE_SORT [$$58(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$52, $$55)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HYBRID_HASH_JOIN [$$55][$$52] |PARTITIONED|
+ join (eq($$55, $$58)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HYBRID_HASH_JOIN [$$58][$$55] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$53, $$55)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HYBRID_HASH_JOIN [$$55][$$53] |PARTITIONED|
+ join (eq($$56, $$58)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HYBRID_HASH_JOIN [$$58][$$56] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$55] |PARTITIONED|
- project ([$$55]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$58] |PARTITIONED|
+ project ([$$58]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$55, $$n] <- tpch.Nation [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ data-scan []<-[$$58, $$n] <- tpch.Nation [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$53] |PARTITIONED|
- project ([$$53]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$56] |PARTITIONED|
+ project ([$$56]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$53] <- [$$s.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$56] <- [$$s.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
project ([$$s]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$56, $$s] <- tpch.Supplier [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ data-scan []<-[$$59, $$s] <- tpch.Supplier [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$52] |PARTITIONED|
- project ([$$52]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$55] |PARTITIONED|
+ project ([$$55]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$52] <- [$$c.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$55] <- [$$c.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
project ([$$c]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$57, $$c] <- tpch.Customer [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ data-scan []<-[$$60, $$c] <- tpch.Customer [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan
index 554d42f..453c83d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan
@@ -1,62 +1,62 @@
-distribute result [$$48] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+distribute result [$$51] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$48]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ project ([$$51]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$48] <- [{"n_nationkey": $$55, "s_nationkey": $$53, "c_nationkey": $$52}] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- SORT_MERGE_EXCHANGE [$$55(ASC), $$53(ASC), $$52(ASC) ] |PARTITIONED|
- order (ASC, $$55) (ASC, $$53) (ASC, $$52) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- STABLE_SORT [$$55(ASC), $$53(ASC), $$52(ASC)] |PARTITIONED|
+ -- SORT_MERGE_EXCHANGE [$$58(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
+ order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- STABLE_SORT [$$58(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$52, $$55)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HYBRID_HASH_JOIN [$$55][$$52] |PARTITIONED|
+ join (eq($$55, $$58)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HYBRID_HASH_JOIN [$$58][$$55] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$53, $$55)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HYBRID_HASH_JOIN [$$55][$$53] |PARTITIONED|
+ join (eq($$56, $$58)) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HYBRID_HASH_JOIN [$$58][$$56] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$55] |PARTITIONED|
- project ([$$55]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$58] |PARTITIONED|
+ project ([$$58]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$55, $$n] <- tpch.Nation [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ data-scan []<-[$$58, $$n] <- tpch.Nation [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$53] |PARTITIONED|
- project ([$$53]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$56] |PARTITIONED|
+ project ([$$56]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$53] <- [$$s.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$56] <- [$$s.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
project ([$$s]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$56, $$s] <- tpch.Supplier [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ data-scan []<-[$$59, $$s] <- tpch.Supplier [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$52] |PARTITIONED|
- project ([$$52]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$55] |PARTITIONED|
+ project ([$$55]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$52] <- [$$c.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$55] <- [$$c.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
project ([$$c]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$57, $$c] <- tpch.Customer [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ data-scan []<-[$$60, $$c] <- tpch.Customer [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan
index b11c296..e7816b3 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan
@@ -1,22 +1,22 @@
-distribute result [$$51] [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+distribute result [$$51] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ project ([$$51]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- SORT_MERGE_EXCHANGE [$$59(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- STABLE_SORT [$$59(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$59, $$56, $$55]) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ project ([$$59, $$56, $$55]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.1E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.1E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 2.1, op-cost: 2000000.0, total-cost: 1.1E7]
+ join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 1.1E7]
-- HYBRID_HASH_JOIN [$$59, $$56][$$55, $$66] |PARTITIONED|
exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-- HASH_PARTITION_EXCHANGE [$$59, $$56] |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan
index c492146..3da3c3e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan
@@ -1,64 +1,64 @@
-distribute result [$$48] [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+distribute result [$$51] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$48]) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+ project ([$$51]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$48] <- [{"n_nationkey": $$56, "s_nationkey": $$53, "c_nationkey": $$52}] [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+ assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
- -- SORT_MERGE_EXCHANGE [$$56(ASC), $$53(ASC), $$52(ASC) ] |PARTITIONED|
- order (ASC, $$56) (ASC, $$53) (ASC, $$52) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
- -- STABLE_SORT [$$56(ASC), $$53(ASC), $$52(ASC)] |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
+ -- SORT_MERGE_EXCHANGE [$$59(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
+ order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
+ -- STABLE_SORT [$$59(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$56, $$53, $$52]) [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+ project ([$$59, $$56, $$55]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 1.0E7]
+ exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1.0E7]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (and(eq($$52, $$56), eq($$53, $$63))) [cardinality: 2.1, op-cost: 2000000.0, total-cost: 1.0E7]
- -- HYBRID_HASH_JOIN [$$56, $$53][$$52, $$63] |PARTITIONED|
+ join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 1.0E7]
+ -- HYBRID_HASH_JOIN [$$59, $$56][$$55, $$66] |PARTITIONED|
exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 6000000.0]
- -- HASH_PARTITION_EXCHANGE [$$56, $$53] |PARTITIONED|
- project ([$$53, $$56]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 5000000.0]
+ -- HASH_PARTITION_EXCHANGE [$$59, $$56] |PARTITIONED|
+ project ([$$56, $$59]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 5000000.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 6000000.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- unnest-map [$$56, $$n] <- index-search("Nation", 0, "tpch", "Nation", true, true, 1, $$53, 1, $$53, true, true, true) [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 5000000.0]
+ unnest-map [$$59, $$n] <- index-search("Nation", 0, "tpch", "Nation", true, true, 1, $$56, 1, $$56, true, true, true) [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 5000000.0]
-- BTREE_SEARCH |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- order (ASC, $$53) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- STABLE_SORT [$$53(ASC)] |PARTITIONED|
+ order (ASC, $$56) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- STABLE_SORT [$$56(ASC)] |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
- -- HASH_PARTITION_EXCHANGE [$$53] |PARTITIONED|
- project ([$$53]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HASH_PARTITION_EXCHANGE [$$56] |PARTITIONED|
+ project ([$$56]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$53] <- [$$s.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
+ assign [$$56] <- [$$s.getField(3)] [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ASSIGN |PARTITIONED|
project ([$$s]) [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$55, $$s] <- tpch.Supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+ data-scan []<-[$$58, $$s] <- tpch.Supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
- -- HASH_PARTITION_EXCHANGE [$$52, $$63] |PARTITIONED|
- assign [$$63] <- [$$52] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+ -- HASH_PARTITION_EXCHANGE [$$55, $$66] |PARTITIONED|
+ assign [$$66] <- [$$55] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-- ASSIGN |PARTITIONED|
- project ([$$52]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+ project ([$$55]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$52] <- [$$c.getField(3)] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+ assign [$$55] <- [$$c.getField(3)] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-- ASSIGN |PARTITIONED|
project ([$$c]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-- STREAM_PROJECT |PARTITIONED|
exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$57, $$c] <- tpch.Customer [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+ data-scan []<-[$$60, $$c] <- tpch.Customer [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan
index 25663a0..0e78a96 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.04.plan
@@ -1,22 +1,22 @@
-distribute result [$$51] [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+distribute result [$$51] [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ project ([$$51]) [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- SORT_MERGE_EXCHANGE [$$58(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- STABLE_SORT [$$58(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$58, $$56, $$55]) [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ project ([$$58, $$56, $$55]) [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (and(eq($$55, $$58), eq($$56, $$66))) [cardinality: 15.0, op-cost: 175.0, total-cost: 560.0]
+ join (and(eq($$55, $$58), eq($$56, $$66))) [cardinality: 150.0, op-cost: 175.0, total-cost: 560.0]
-- HYBRID_HASH_JOIN [$$55, $$66][$$58, $$56] |PARTITIONED|
exchange [cardinality: 150.0, op-cost: 150.0, total-cost: 300.0]
-- HASH_PARTITION_EXCHANGE [$$55, $$66] |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan
index 2ace4af..b4a0891 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.10.plan
@@ -1,22 +1,22 @@
-distribute result [$$51] [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+distribute result [$$51] [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ project ([$$51]) [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- SORT_MERGE_EXCHANGE [$$58(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- STABLE_SORT [$$58(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$58, $$56, $$55]) [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ project ([$$58, $$56, $$55]) [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (and(eq($$55, $$58), eq($$56, $$66))) [cardinality: 15.0, op-cost: 225.0, total-cost: 500.0]
+ join (and(eq($$55, $$58), eq($$56, $$66))) [cardinality: 150.0, op-cost: 225.0, total-cost: 500.0]
-- HYBRID_HASH_JOIN [$$55, $$66][$$58, $$56] |PARTITIONED|
exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 150.0]
-- RANDOM_PARTITION_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan
index 354a94b..5bf8d6d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.12.plan
@@ -1,18 +1,18 @@
-distribute result [$$51] [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+distribute result [$$51] [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+ project ([$$51]) [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+ assign [$$51] <- [{"n_nationkey": $$58, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- SORT_MERGE_EXCHANGE [$$58(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+ order (ASC, $$58) (ASC, $$56) (ASC, $$55) [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- STABLE_SORT [$$58(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 605.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 605.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$55, $$58)) [cardinality: 15.0, op-cost: 175.0, total-cost: 605.0]
+ join (eq($$55, $$58)) [cardinality: 150.0, op-cost: 175.0, total-cost: 605.0]
-- HYBRID_HASH_JOIN [$$55][$$58] |PARTITIONED|
exchange [cardinality: 150.0, op-cost: 150.0, total-cost: 300.0]
-- HASH_PARTITION_EXCHANGE [$$55] |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan
index 66124a1..ea91cd5 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.14.plan
@@ -1,22 +1,22 @@
-distribute result [$$51] [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+distribute result [$$51] [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ project ([$$51]) [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- SORT_MERGE_EXCHANGE [$$59(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- STABLE_SORT [$$59(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$59, $$56, $$55]) [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ project ([$$59, $$56, $$55]) [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 560.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 560.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 15.0, op-cost: 175.0, total-cost: 560.0]
+ join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 150.0, op-cost: 175.0, total-cost: 560.0]
-- HYBRID_HASH_JOIN [$$55, $$66][$$59, $$56] |PARTITIONED|
exchange [cardinality: 150.0, op-cost: 150.0, total-cost: 300.0]
-- HASH_PARTITION_EXCHANGE [$$55, $$66] |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan
index 0b31760..2700e8a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.16.plan
@@ -1,22 +1,22 @@
-distribute result [$$51] [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+distribute result [$$51] [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- DISTRIBUTE_RESULT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$51]) [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ project ([$$51]) [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ assign [$$51] <- [{"n_nationkey": $$59, "s_nationkey": $$56, "c_nationkey": $$55}] [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ASSIGN |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- SORT_MERGE_EXCHANGE [$$59(ASC), $$56(ASC), $$55(ASC) ] |PARTITIONED|
- order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ order (ASC, $$59) (ASC, $$56) (ASC, $$55) [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- STABLE_SORT [$$59(ASC), $$56(ASC), $$55(ASC)] |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- project ([$$59, $$56, $$55]) [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ project ([$$59, $$56, $$55]) [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 15.0, op-cost: 0.0, total-cost: 500.0]
+ exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 500.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 15.0, op-cost: 225.0, total-cost: 500.0]
+ join (and(eq($$55, $$59), eq($$56, $$66))) [cardinality: 150.0, op-cost: 225.0, total-cost: 500.0]
-- HYBRID_HASH_JOIN [$$55, $$66][$$59, $$56] |PARTITIONED|
exchange [cardinality: 150.0, op-cost: 0.0, total-cost: 150.0]
-- RANDOM_PARTITION_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.3.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.3.plan
index 38c5f61..49f6ad2 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.3.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.3.plan
@@ -1,18 +1,18 @@
-distribute result [$$c] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+distribute result [$$c] [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 5 offset 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 5 offset 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- limit 10 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 10 [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 1152.42]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$18, $$19, $$c] <- test.LineItem condition (and(lt($$c.getField(2), 150), lt($$c.getField(5), 10000))) limit 10 [cardinality: 6005.0, op-cost: 6005.0, total-cost: 6005.0]
+ data-scan []<-[$$18, $$19, $$c] <- test.LineItem condition (and(lt($$c.getField(2), 150), lt($$c.getField(5), 10000))) limit 10 [cardinality: 6005.0, op-cost: 1152.42, total-cost: 1152.42]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.5.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.5.plan
index a9d2b4f..3b85e2a 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.5.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup-select/push-limit-to-primary-lookup-select.5.plan
@@ -1,24 +1,24 @@
-distribute result [$$20] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+distribute result [$$20] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- project ([$$20]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ project ([$$20]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$20] <- [{"shipdate": substring($$c.getField(10), 0, 4), "suppkey": gt($$21, 0)}] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ assign [$$20] <- [{"shipdate": substring($$c.getField(10), 0, 4), "suppkey": gt($$21, 0)}] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ASSIGN |PARTITIONED|
- limit 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_LIMIT |PARTITIONED|
- assign [$$21] <- [$$c.getField(2)] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ assign [$$21] <- [$$c.getField(2)] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ASSIGN |PARTITIONED|
- project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$22, $$23, $$c] <- test.LineItem condition (lt($$c.getField(2), 150)) limit 5 [cardinality: 6005.0, op-cost: 6005.0, total-cost: 6005.0]
+ data-scan []<-[$$22, $$23, $$c] <- test.LineItem condition (lt($$c.getField(2), 150)) limit 5 [cardinality: 6005.0, op-cost: 6010.65, total-cost: 6010.65]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.3.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.3.plan
index f5fb51e..96d3acf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.3.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.3.plan
@@ -1,18 +1,18 @@
-distribute result [$$c] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+distribute result [$$c] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 5 offset 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 5 offset 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- limit 10 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 10 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$15, $$16, $$c] <- test.LineItem condition (lt($$c.getField(2), 150)) limit 10 [cardinality: 6005.0, op-cost: 6005.0, total-cost: 6005.0]
+ data-scan []<-[$$15, $$16, $$c] <- test.LineItem condition (lt($$c.getField(2), 150)) limit 10 [cardinality: 6005.0, op-cost: 6010.65, total-cost: 6010.65]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.5.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.5.plan
index 7aa0db8..383e104 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.5.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-lookup/push-limit-to-primary-lookup.5.plan
@@ -1,18 +1,18 @@
-distribute result [$$c] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+distribute result [$$c] [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 5 offset 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 5 offset 5 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- limit 10 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ limit 10 [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ project ([$$c]) [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6005.0]
+ exchange [cardinality: 6005.0, op-cost: 0.0, total-cost: 6010.65]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$17, $$18, $$c] <- test.LineItem condition (lt($$c.getField(2), 150)) limit 10 [cardinality: 6005.0, op-cost: 6005.0, total-cost: 6005.0]
+ data-scan []<-[$$17, $$18, $$c] <- test.LineItem condition (lt($$c.getField(2), 150)) limit 10 [cardinality: 6005.0, op-cost: 6010.65, total-cost: 6010.65]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.3.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.3.plan
index 6427067..7c2bdbe 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.3.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.3.plan
@@ -1,18 +1,18 @@
-distribute result [$$paper] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+distribute result [$$paper] [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 5 offset 5 [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ limit 5 offset 5 [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- limit 10 [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ limit 10 [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$paper]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$paper]) [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 24.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$15, $$paper] <- test.DBLP1 condition (contains($$paper.getField(1), "kimL89")) limit 10 [cardinality: 100.0, op-cost: 100.0, total-cost: 100.0]
+ data-scan []<-[$$15, $$paper] <- test.DBLP1 condition (contains($$paper.getField(1), "kimL89")) limit 10 [cardinality: 100.0, op-cost: 24.0, total-cost: 24.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.5.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.5.plan
index e175907..fb2c1fd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.5.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.5.plan
@@ -1,24 +1,24 @@
-distribute result [$$37] [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+distribute result [$$37] [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 2 [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ limit 2 [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- project ([$$37]) [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ project ([$$37]) [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$37] <- [{"dblpid": $$38}] [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ assign [$$37] <- [{"dblpid": $$38}] [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- ASSIGN |PARTITIONED|
- limit 2 [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ limit 2 [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$38]) [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ project ([$$38]) [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 600.0]
+ exchange [cardinality: 2.1, op-cost: 0.0, total-cost: 205.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- join (eq($$38, $$41)) [cardinality: 100.0, op-cost: 200.0, total-cost: 600.0]
+ join (eq($$38, $$41)) [cardinality: 2.1, op-cost: 100.0, total-cost: 205.0]
-- HYBRID_HASH_JOIN [$$38][$$41] |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 100.0, total-cost: 200.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
-- HASH_PARTITION_EXCHANGE [$$38] |PARTITIONED|
project ([$$38]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
-- STREAM_PROJECT |PARTITIONED|
@@ -26,7 +26,7 @@
-- ASSIGN |PARTITIONED|
project ([$$d]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 100.0, total-cost: 200.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
data-scan []<-[$$39, $$d] <- test.DBLP1 [cardinality: 100.0, op-cost: 100.0, total-cost: 100.0]
-- DATASOURCE_SCAN |PARTITIONED|
@@ -34,29 +34,29 @@
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
empty-tuple-source [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- EMPTY_TUPLE_SOURCE |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 100.0, total-cost: 200.0]
+ exchange [cardinality: 100.0, op-cost: 4.0, total-cost: 5.0]
-- HASH_PARTITION_EXCHANGE [$$41] |PARTITIONED|
- project ([$$41]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$41]) [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |UNPARTITIONED|
- assign [$$41] <- [get-item($$30, 0).getField(0).getField(1)] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ assign [$$41] <- [get-item($$30, 0).getField(0).getField(1)] [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |UNPARTITIONED|
- aggregate [$$30] <- [listify($$29)] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ aggregate [$$30] <- [listify($$29)] [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- AGGREGATE |UNPARTITIONED|
- limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 100.0, total-cost: 200.0]
+ exchange [cardinality: 100.0, op-cost: 4.0, total-cost: 5.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- project ([$$29]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$29]) [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$29] <- [{"d": $$d}] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ assign [$$29] <- [{"d": $$d}] [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- ASSIGN |PARTITIONED|
- limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$d]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$d]) [cardinality: 100.0, op-cost: 0.0, total-cost: 1.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 100.0, total-cost: 200.0]
+ exchange [cardinality: 100.0, op-cost: 4.0, total-cost: 5.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$40, $$d] <- test.DBLP1 condition (ends-with($$d.getField(1), "Blakeley95")) limit 1 [cardinality: 100.0, op-cost: 100.0, total-cost: 100.0]
+ data-scan []<-[$$40, $$d] <- test.DBLP1 condition (ends-with($$d.getField(1), "Blakeley95")) limit 1 [cardinality: 100.0, op-cost: 1.0, total-cost: 1.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.6.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.6.plan
index 9312e62..26ba31b 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.6.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.6.plan
@@ -1,26 +1,26 @@
-distribute result [$$19] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+distribute result [$$19] [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- project ([$$19]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$19]) [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$19] <- [{"$1": substring($$20, 0, 21)}] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ assign [$$19] <- [{"$1": substring($$20, 0, 21)}] [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- ASSIGN |PARTITIONED|
- limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ limit 1 [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$20]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$20]) [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$20] <- [$$DBLP1.getField(1)] [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ assign [$$20] <- [$$DBLP1.getField(1)] [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- ASSIGN |PARTITIONED|
- project ([$$DBLP1]) [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ project ([$$DBLP1]) [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 100.0]
+ exchange [cardinality: 100.0, op-cost: 0.0, total-cost: 2.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$21, $$DBLP1] <- test.DBLP1 condition (gt($$DBLP1.getField(1), "series")) limit 1 [cardinality: 100.0, op-cost: 100.0, total-cost: 100.0]
+ data-scan []<-[$$21, $$DBLP1] <- test.DBLP1 condition (gt($$DBLP1.getField(1), "series")) limit 1 [cardinality: 100.0, op-cost: 2.0, total-cost: 2.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.8.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.8.plan
index 190a98e..8c007cf 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.8.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/limit/push-limit-to-primary-scan-select/push-limit-to-primary-scan-select.8.plan
@@ -1,26 +1,26 @@
-distribute result [$$22] [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+distribute result [$$22] [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- DISTRIBUTE_RESULT |UNPARTITIONED|
- exchange [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ exchange [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
- limit 2 [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ limit 2 [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- STREAM_LIMIT |UNPARTITIONED|
- exchange [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ exchange [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- RANDOM_MERGE_EXCHANGE |PARTITIONED|
- limit 2 [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ limit 2 [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- STREAM_LIMIT |PARTITIONED|
- project ([$$22]) [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ project ([$$22]) [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$22] <- [$$26.getField("lang")] [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ assign [$$22] <- [$$26.getField("lang")] [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- ASSIGN |PARTITIONED|
- project ([$$26]) [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ project ([$$26]) [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- STREAM_PROJECT |PARTITIONED|
- assign [$$26] <- [$$t.getField("user")] [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ assign [$$26] <- [$$t.getField("user")] [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- ASSIGN |PARTITIONED|
- project ([$$t]) [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ project ([$$t]) [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- STREAM_PROJECT |PARTITIONED|
- exchange [cardinality: 12.0, op-cost: 0.0, total-cost: 12.0]
+ exchange [cardinality: 12.0, op-cost: 0.0, total-cost: 3.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- data-scan []<-[$$25, $$t] <- test.TweetMessages condition (and(ge($$t.getField("user").getField("friends_count"), 0), le($$t.getField("user").getField("friends_count"), 150))) limit 2 [cardinality: 12.0, op-cost: 12.0, total-cost: 12.0]
+ data-scan []<-[$$25, $$t] <- test.TweetMessages condition (and(ge($$t.getField("user").getField("friends_count"), 0), le($$t.getField("user").getField("friends_count"), 150))) limit 2 [cardinality: 12.0, op-cost: 3.0, total-cost: 3.0]
-- DATASOURCE_SCAN |PARTITIONED|
exchange [cardinality: 0.0, op-cost: 0.0, total-cost: 0.0]
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|