[ASTERIXDB-3600][COMP] cardinality improvements

Ext-Ref: MB-66327

Change-Id: I3287d014f97369d7def85288894c23a0fcd977cd
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19729
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: <preetham02@apache.org>
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 148ace9..8406520 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
@@ -107,6 +107,7 @@
 
     private List<Triple<ILogicalOperator, ILogicalOperator, List<ILogicalOperator>>> modifyUnnestInfo;
     private final Map<DataSourceScanOperator, Boolean> fakeLeafInputsMap = new HashMap();
+    ILogicalOperator newRootAfterUnnest = null;
 
     public EnumerateJoinsRule(JoinEnum joinEnum) {
         this.joinEnum = joinEnum;
@@ -307,7 +308,10 @@
                 modifyUnnestInfo = new ArrayList<>();
                 collectUnnestModificationInfo(null, root, cheapestPlanNode);
                 for (int k = 0; k < modifyUnnestInfo.size(); k++) {
-                    root = modifyTree(null, root, k);
+                    modifyTree(null, root, k);
+                    if (newRootAfterUnnest != null) {
+                        root = newRootAfterUnnest;
+                    }
                 }
                 Mutable<ILogicalOperator> rootRef = new MutableObject<>(root);
                 if (LOGGER.isTraceEnabled()) {
@@ -367,7 +371,7 @@
 
     private boolean everyLeafInputDoesNotHaveADataScanOperator(List<ILogicalOperator> leafInputs) {
         for (ILogicalOperator leafInput : leafInputs) {
-            DataSourceScanOperator scanOp = (DataSourceScanOperator) findDataSourceScanOperator(leafInput);
+            DataSourceScanOperator scanOp = joinEnum.findDataSourceScanOperator(leafInput);
             if (scanOp == null) {
                 return true;
             }
@@ -380,35 +384,31 @@
         return false;
     }
 
-    private ILogicalOperator modifyTree(ILogicalOperator parent, ILogicalOperator op, int k) {
-
+    private void modifyTree(ILogicalOperator parent, ILogicalOperator op, int k) {
         if (modifyUnnestInfo.get(k).second == op) { // found the one to get rid off; this should be an OJ
             int size = modifyUnnestInfo.get(k).third.size();
-            modifyUnnestInfo.get(k).third.get(size - 1).getInputs().get(0).setValue(op.getInputs().get(0).getValue()); //The unnestOp is at the lowest position and points to the op below it.
-            if (parent == null) {
-                ILogicalOperator root = modifyUnnestInfo.get(k).third.get(0); // the first assign that belongs to this unnestOp. Or an only one UnnestOp with no assigns
-                ILogicalOperator q = root;
+            UnnestOperator uOp = (UnnestOperator) modifyUnnestInfo.get(k).third.get(size - 1); // UnnestOp is always at the end
+            uOp.getInputs().get(0).setValue(op.getInputs().get(0).getValue()); //The unnestOp is at the lowest position and points to the op below it.
+            if (parent == null) { // change is happening at the very top, so the root will change
+                newRootAfterUnnest = modifyUnnestInfo.get(k).third.get(0); // the first assign that belongs to this unnestOp. Or an only one UnnestOp with no assigns
+                ILogicalOperator q = newRootAfterUnnest;
                 if (modifyUnnestInfo.get(k).third.size() > 1) {
                     for (ILogicalOperator p : modifyUnnestInfo.get(k).third) {
                         q.getInputs().get(0).setValue(p);
                         q = p;
                     }
                 }
-                return root;
             } else {
                 ILogicalOperator q = parent;
                 for (ILogicalOperator p : modifyUnnestInfo.get(k).third) {
                     q.getInputs().get(0).setValue(p);
                     q = p;
                 }
-                return parent;
             }
-
         }
         for (Mutable<ILogicalOperator> input : op.getInputs()) {
-            return modifyTree(op, input.getValue(), k);
+            modifyTree(op, input.getValue(), k);
         }
-        return null;
     }
 
     // This is a complicated routine. Removes unnestOperations from leafInputs. They will be added back at the right places.
@@ -502,7 +502,7 @@
     }
 
     private ILogicalOperator truncateInput(ILogicalOperator op) throws AlgebricksException {
-        ILogicalOperator dsOp = findDataSourceScanOperator(op);
+        ILogicalOperator dsOp = joinEnum.findDataSourceScanOperator(op);
         ILogicalOperator ds = OperatorManipulationUtil.bottomUpCopyOperators(dsOp);
         return ds;
     }
@@ -1171,6 +1171,7 @@
     /**
      * Finds the DataSourceScanOperator given a leafInput
      */
+    /*
     private ILogicalOperator findDataSourceScanOperator(ILogicalOperator op) {
         ILogicalOperator origOp = op;
         while (op != null && op.getOperatorTag() != LogicalOperatorTag.EMPTYTUPLESOURCE) {
@@ -1181,6 +1182,8 @@
         }
         return null;
     }
+    
+     */
 
     private void removeJoinAnnotations(AbstractFunctionCallExpression afcExpr) {
         afcExpr.removeAnnotation(BroadcastExpressionAnnotation.class);
@@ -1262,7 +1265,7 @@
         if (selOp != null) {
             addCardCostAnnotations(selOp, plan);
         }
-        addCardCostAnnotations(findDataSourceScanOperator(leftInput), plan);
+        addCardCostAnnotations(joinEnum.findDataSourceScanOperator(leftInput), plan);
     }
 
     private void getJoinNode(PlanNode plan, List<JoinOperator> allJoinOps) throws AlgebricksException {
@@ -1374,7 +1377,7 @@
             joinOp.getInputs().get(0).setValue(leftInput);
             ILogicalOperator op = joinOp.getInputs().get(0).getValue();
             context.computeAndSetTypeEnvironmentForOperator(op);
-            addCardCostAnnotations(findDataSourceScanOperator(leftInput), leftPlan);
+            addCardCostAnnotations(joinEnum.findDataSourceScanOperator(leftInput), leftPlan);
         } else {
             // join
             totalNumberOfJoins.increment();
@@ -1394,7 +1397,7 @@
             }
             joinOp.getInputs().get(1).setValue(rightInput);
             context.computeAndSetTypeEnvironmentForOperator(joinOp.getInputs().get(1).getValue());
-            addCardCostAnnotations(findDataSourceScanOperator(rightInput), rightPlan);
+            addCardCostAnnotations(joinEnum.findDataSourceScanOperator(rightInput), rightPlan);
         } else {
             // join
             totalNumberOfJoins.increment();
@@ -1484,7 +1487,7 @@
             throws AlgebricksException {
         int n = 0;
         for (ILogicalOperator li : leafInputs) {
-            DataSourceScanOperator scanOp = (DataSourceScanOperator) findDataSourceScanOperator(li);
+            DataSourceScanOperator scanOp = joinEnum.findDataSourceScanOperator(li);
             if (scanOp == null) {
                 continue;
             }
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 f37f8a3..0f4cc82 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
@@ -43,7 +43,7 @@
     protected int leftSideBits;
     protected int rightSideBits;
     protected int numLeafInputs;
-    protected double selectivity;
+    protected double selectivity = -1.0; // This must be changed obviously
     protected comparisonOp comparisonType;
     protected JoinOperator joinOp = null;
     protected List<LogicalVariable> usedVars = null;
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 4be0e66..73be298 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
@@ -677,26 +677,100 @@
         return null;
     }
 
-    // in case we have l.partkey = ps.partkey and l.suppkey = ps.suppkey, we will only use the first one for cardinality computations.
-    // treat it like a Pk-Fk join; simplifies cardinality computation
-    private void markCompositeJoinPredicates() {
-        // can use dataSetBits??? This will be simpler.
-        for (int i = 0; i < joinConditions.size() - 1; i++) {
+    // This is basically a heuristic routine. Not guaranteed to be 100% accurate.
+    // Use only when primary keys are not defined (shadow data sets)
+    // Examples l.partkey = ps.partkey and l.suppkey = ps.suppkey TPCH
+    // c.c_d_id = o.o_d_id and c.c_w_id = o.o_w_id and c.c_id = o.o_c_id in CH2
+    //for (JoinCondition jc : joinConditions) {
+    //jc.selectivity = stats.getSelectivityFromAnnotationMain(jc, null, true, false, jc.joinOp);
+    //}
+    private void markCompositeJoinPredicates() throws AlgebricksException {
+        List<JoinCondition> JCs = new ArrayList<>();
+        for (int i = 0; i < joinConditions.size(); i++) {
             JoinCondition jcI = joinConditions.get(i);
-            if (jcI.comparisonType == JoinCondition.comparisonOp.OP_EQ && !jcI.partOfComposite) {
+            if (jcI.usedVars == null || jcI.usedVars.size() != 2 || jcI.numLeafInputs != 2 || jcI.partOfComposite) {
+                continue;
+            }
+            JCs.clear();
+            JCs.add(jcI);
+            if (jcI.comparisonType == JoinCondition.comparisonOp.OP_EQ) {
                 for (int j = i + 1; j < joinConditions.size(); j++) {
                     JoinCondition jcJ = joinConditions.get(j);
-                    if (jcJ.comparisonType == JoinCondition.comparisonOp.OP_EQ && jcI.datasetBits == jcJ.datasetBits) {
-                        jcI.selectivity = 1.0 / smallerDatasetSize(jcI.datasetBits);
-                        // 1/P will be the selectivity of the composite clause
-                        jcJ.partOfComposite = true;
-                        jcJ.selectivity = 1.0;
+                    if (jcJ.usedVars == null) {
+                        continue;
                     }
+                    if (jcJ.comparisonType == JoinCondition.comparisonOp.OP_EQ && (jcJ.usedVars.size() == 2)
+                            && (jcJ.numLeafInputs == 2) && (jcI.datasetBits == jcJ.datasetBits)) {
+                        JCs.add(jcJ);
+                    }
+                }
+                double sel = checkForPrimaryKey(JCs);
+                //if (JCs.size() > 1) { // need at least two to form a composite join key
+                // Now check if selectivities have to be adjusted for this composite key
+                if (JCs.size() > 1) {
+                    for (JoinCondition jc : JCs) {
+                        jc.partOfComposite = true;
+                    }
+                }
+                if (sel == -1.0) {
+                    for (JoinCondition jc : JCs) {
+                        jc.selectivity = stats.getSelectivityFromAnnotationMain(jc, null, true, false, jc.joinOp);
+                    }
+
+                } else {
+                    for (JoinCondition jc : JCs) {
+                        jc.selectivity = 1.0;
+                    }
+                    JCs.get(0).selectivity = sel; // store this in the first condition. Does not matter which one it is!
                 }
             }
         }
     }
 
+    // at this point the join is binary. Not sure if all the predicates may not be in the same order?? Appears to be the case
+    private double checkForPrimaryKey(List<JoinCondition> jCs) {
+        List<LogicalVariable> leftVars = new ArrayList<>();
+        List<LogicalVariable> rightVars = new ArrayList<>();
+        for (JoinCondition jc : jCs) {
+            leftVars.add(jc.usedVars.get(0));
+            rightVars.add(jc.usedVars.get(1));
+        }
+        double sel = -1.0;
+        ILogicalOperator leftLeafInput = leafInputs.get(jCs.get(0).leftSide - 1);
+        DataSourceScanOperator leftScanOp = findDataSourceScanOperator(leftLeafInput);
+        boolean leftPrimary = false;
+        if (leftScanOp.getVariables().containsAll(leftVars)
+                && leftScanOp.getVariables().size() == leftVars.size() + 1) {
+            // this is the primary side
+            leftPrimary = true;
+            sel = 1.0 / jnArray[jCs.get(0).leftSide].getOrigCardinality();
+        }
+        boolean rightPrimary = false;
+        ILogicalOperator rightLeafInput = leafInputs.get(jCs.get(0).rightSide - 1);
+        DataSourceScanOperator rightScanOp = findDataSourceScanOperator(rightLeafInput);
+        if (rightScanOp.getVariables().containsAll(rightVars)
+                && rightScanOp.getVariables().size() == rightVars.size() + 1) {
+            // this is the primary side
+            rightPrimary = true;
+            sel = 1.0 / jnArray[jCs.get(0).rightSide].getOrigCardinality();
+        }
+
+        if (leftPrimary && rightPrimary) {
+            // this is the subset case. The join cardinality will be the smaller side. So selectvity will be 1/biggerCard
+            sel = 1.0 / Math.max(jnArray[jCs.get(0).leftSide].getOrigCardinality(),
+                    jnArray[jCs.get(0).rightSide].getOrigCardinality());
+        }
+        return sel;
+    }
+
+    private boolean close(double size1, double size2) {
+        double ratio = size1 / size2;
+        if (ratio > 0.8 && ratio < 1.2) {
+            return true;
+        }
+        return false;
+    }
+
     private double smallerDatasetSize(int datasetBits) {
         double size = Cost.MAX_CARD;
         for (JoinNode jn : this.jnArray)
@@ -899,16 +973,15 @@
                     jn.datasetIndexes = new ArrayList<>();
                     jn.datasetIndexes.addAll(jnI.datasetIndexes);
                     jn.datasetIndexes.addAll(jnJ.datasetIndexes);
-                    Collections.sort(jn.datasetIndexes);
 
                     jn.datasetNames = new ArrayList<>();
                     jn.datasetNames.addAll(jnI.datasetNames);
                     jn.datasetNames.addAll(jnJ.datasetNames);
-                    Collections.sort(jn.datasetNames);
+
                     jn.aliases = new ArrayList<>();
                     jn.aliases.addAll(jnI.aliases);
                     jn.aliases.addAll(jnJ.aliases);
-                    Collections.sort(jn.aliases);
+
                     jn.size = jnI.size + jnJ.size; // These are the original document sizes
                     jn.setCardinality(jn.computeJoinCardinality(), true);
                     jn.setSizeVarsAfterScan(jnI.getSizeVarsAfterScan() + jnJ.getSizeVarsAfterScan());
@@ -1272,10 +1345,13 @@
         }
 
         for (JoinCondition jc : joinConditions) {
-            jc.selectivity = stats.getSelectivityFromAnnotationMain(jc, null, true, false, jc.joinOp);
+            if (!((AbstractFunctionCallExpression) jc.joinCondition).getFunctionIdentifier()
+                    .equals(AlgebricksBuiltinFunctions.EQ)) {
+                jc.selectivity = stats.getSelectivityFromAnnotationMain(jc, null, true, false, jc.joinOp);
+            }
         }
 
-        findSelectionPredsInsideJoins(); // This was added to make TPCH Q7 work.
+        findSelectionPredsInsideJoins(); // This was added to make TPCH Q7 work. cleanup/redo. difficult to debug currently
         findIfJoinGraphIsConnected();
 
         if (LOGGER.isTraceEnabled()) {
@@ -1283,14 +1359,19 @@
         }
 
         markCompositeJoinPredicates();
+        for (JoinCondition jc : joinConditions) {
+            if (jc.selectivity == -1) {// just in case we missed computing some selectivities perhaps because there were no keys found
+                jc.selectivity = stats.getSelectivityFromAnnotationMain(jc, null, true, false, jc.joinOp);
+            }
+        }
         int lastJnNum = enumerateHigherLevelJoinNodes();
         JoinNode lastJn = jnArray[allTabsJnNum];
+        // return the cheapest plan
         if (LOGGER.isTraceEnabled()) {
             EnumerateJoinsRule.printPlan(pp, op, "Original Whole plan in JN END");
             LOGGER.trace(dumpJoinNodes(lastJnNum));
         }
 
-        // return the cheapest plan
         return lastJn.cheapestPlanIndex;
     }
 
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 2aa93a7..3451966 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
@@ -19,6 +19,8 @@
 
 package org.apache.asterix.optimizer.rules.cbo;
 
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -513,9 +515,17 @@
 
     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) {
+            if (!jc1.partOfComposite)
+                return jc1.selectivity;
+            if (!jc2.partOfComposite)
+                return jc2.selectivity;
+            if (!jc3.partOfComposite)
+                return jc3.selectivity;
+            // one of the above must be true.
             sel = findRedundantSel(jc1, jc2, jc3);
         } else {
             // at least one of the predicates in not an equality predicate
@@ -1591,6 +1601,8 @@
 
     @Override
     public String toString() {
+        NumberFormat scientificFormat = new DecimalFormat("0.###E0");
+        DecimalFormat formatter = new DecimalFormat("#,###.00");
         List<PlanNode> allPlans = joinEnum.getAllPlans();
         StringBuilder sb = new StringBuilder(128);
         if (IsBaseLevelJoinNode()) {
@@ -1615,9 +1627,16 @@
         sb.append("level ").append(level).append('\n');
         sb.append("highestDatasetId ").append(highestDatasetId).append('\n');
         if (IsBaseLevelJoinNode()) {
-            sb.append("orig cardinality ").append(dumpDouble(origCardinality));
+            //sb.append("orig cardinality ").append(dumpDouble(origCardinality));
+            //sb.append("orig cardinality ").append(dumpDouble(Double.parseDouble(scientificFormat.format(origCardinality))));
+            sb.append("orig cardinality2 ")
+                    .append(formatter.format(Double.parseDouble(String.valueOf(origCardinality))));
+            sb.append("\n    cardinality \n").append(formatter.format(Double.parseDouble(String.valueOf(cardinality))));
+        } else {
+            //sb.append("cardinality ").append(dumpDouble(cardinality));
+            //sb.append("cardinality ").append(dumpDouble(Double.parseDouble(scientificFormat.format(cardinality))));
+            sb.append("cardinality \n").append(formatter.format(Double.parseDouble(String.valueOf(cardinality))));
         }
-        sb.append("cardinality ").append(dumpDouble(cardinality));
         sb.append("size ").append(dumpDouble(size));
         sb.append("outputSize(sizeVarsAfterScan) ").append(dumpDouble(sizeVarsAfterScan));
         if (planIndexesArray.size() == 0) {
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 4f5688a..18bc53f 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
@@ -181,36 +181,48 @@
                 return 0.5; // this may not be accurate obviously!
             } // we can do all relops here and other joins such as interval joins and spatial joins, the compile time might increase a lot
 
+            boolean unnestOp1 = joinEnum.findUnnestOp(joinEnum.leafInputs.get(idx1 - 1));
+            boolean unnestOp2 = joinEnum.findUnnestOp(joinEnum.leafInputs.get(idx2 - 1));
+            boolean unnestOp = unnestOp1 || unnestOp2;
             Index.SampleIndexDetails idxDetails1 = (Index.SampleIndexDetails) index1.getIndexDetails();
             Index.SampleIndexDetails idxDetails2 = (Index.SampleIndexDetails) index2.getIndexDetails();
-            if ((idxDetails1.getSourceCardinality() < idxDetails1.getSampleCardinalityTarget())
+            if (((idxDetails1.getSourceCardinality() < idxDetails1.getSampleCardinalityTarget())
                     || (idxDetails2.getSourceCardinality() < idxDetails2.getSampleCardinalityTarget())
-                    || exprUsedVars.size() > 2) { //* if there are more than 2 variables, it is not a simple join like r.a op s.a
-                double sel = findJoinSelFromSamples(joinEnum.leafInputs.get(idx1 - 1),
+                    || exprUsedVars.size() > 2) && !unnestOp) { //* if there are more than 2 variables, it is not a simple join like r.a op s.a
+                double sels = findJoinSelFromSamples(joinEnum.leafInputs.get(idx1 - 1),
                         joinEnum.leafInputs.get(idx2 - 1), index1, index2, joinExpr, jOp);
-                if (sel == 0.0) {
-                    sel = 1.0 / Math.max(card1, card2);
+                if (sels == 0.0) {
+                    sels = 1.0 / Math.max(card1, card2);
                 }
-                return sel;
+                return sels;
             }
             // Now we can handle only equi joins. We make all the uniform and independence assumptions here.
-            double sel = naiveJoinSelectivity(exprUsedVars, card1, card2, idx1, idx2);
-            return sel;
+            double seln = naiveJoinSelectivity(exprUsedVars, card1, card2, idx1, idx2, unnestOp1, unnestOp2);
+            return seln;
         }
     }
 
     private double naiveJoinSelectivity(List<LogicalVariable> exprUsedVars, double card1, double card2, int idx1,
-            int idx2) throws AlgebricksException {
+            int idx2, boolean unnestOp1, boolean unnestOp2) throws AlgebricksException {
         ILogicalOperator leafInput;
         LogicalVariable var;
 
-        // choose the smaller side sample; better results this way for sure!
-        if (card1 < card2) {
+        if (unnestOp1) {// we cannot choose teh side with an array as we need the unnesting scaling factor also.
+                            // have to see if there are other alternatives later
+            leafInput = joinEnum.leafInputs.get(idx2 - 1);
+            var = exprUsedVars.get(1);
+        } else if (unnestOp2) {
             leafInput = joinEnum.leafInputs.get(idx1 - 1);
             var = exprUsedVars.get(0);
         } else {
-            leafInput = joinEnum.leafInputs.get(idx2 - 1);
-            var = exprUsedVars.get(1);
+            // choose the smaller side sample; better results this way for sure!
+            if (card1 < card2) {
+                leafInput = joinEnum.leafInputs.get(idx1 - 1);
+                var = exprUsedVars.get(0);
+            } else {
+                leafInput = joinEnum.leafInputs.get(idx2 - 1);
+                var = exprUsedVars.get(1);
+            }
         }
         Index index = findIndex(leafInput);
         if (index == null) {
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q10.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q10.plan
index b9cf3b6..6f38358 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q10.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q10.plan
@@ -1,98 +1,98 @@
-distribute result [$$159] [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+distribute result [$$159] [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+  exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    limit 20 [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+    limit 20 [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
     -- STREAM_LIMIT  |UNPARTITIONED|
-      assign [$$159] <- [{"c_id": $$c_id, "c_last": $$c_last, "revenue": $$175, "c_city": $$c_city, "c_phone": $$c_phone, "n_name": $$n_name}] project: [$$159] [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+      assign [$$159] <- [{"c_id": $$c_id, "c_last": $$c_last, "revenue": $$175, "c_city": $$c_city, "c_phone": $$c_phone, "n_name": $$n_name}] project: [$$159] [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
       -- ASSIGN  |PARTITIONED|
-        exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+        exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
         -- SORT_MERGE_EXCHANGE [$$175(DESC) ]  |PARTITIONED|
-          limit 20 [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+          limit 20 [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
           -- STREAM_LIMIT  |PARTITIONED|
-            exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+            exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              order (topK: 20) (DESC, $$175) [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+              order (topK: 20) (DESC, $$175) [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
               -- STABLE_SORT [topK: 20] [$$175(DESC)]  |PARTITIONED|
-                exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+                exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                   group by ([$$c_id := $$184; $$c_last := $$185; $$c_city := $$186; $$c_phone := $$187; $$n_name := $$188]) decor ([]) {
-                            aggregate [$$175] <- [agg-global-sql-sum($$183)]
+                            aggregate [$$175] <- [agg-global-sql-sum($$183)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- AGGREGATE  |LOCAL|
-                              nested tuple source
+                              nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- NESTED_TUPLE_SOURCE  |LOCAL|
-                         } [cardinality: 0.0, op-cost: 0.0, total-cost: 2.600009E7]
+                         } [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                   -- SORT_GROUP_BY[$$184, $$185, $$186, $$187, $$188]  |PARTITIONED|
-                    exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+                    exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                     -- HASH_PARTITION_EXCHANGE [$$184, $$185, $$186, $$187, $$188]  |PARTITIONED|
                       group by ([$$184 := $$166; $$185 := $$161; $$186 := $$162; $$187 := $$163; $$188 := $$164]) decor ([]) {
-                                aggregate [$$183] <- [agg-local-sql-sum($$156)]
+                                aggregate [$$183] <- [agg-local-sql-sum($$156)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- AGGREGATE  |LOCAL|
-                                  nested tuple source
+                                  nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
-                             } [cardinality: 0.0, op-cost: 0.0, total-cost: 2.600009E7]
+                             } [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                       -- SORT_GROUP_BY[$$166, $$161, $$162, $$163, $$164]  |PARTITIONED|
-                        exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+                        exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          project ([$$156, $$166, $$161, $$162, $$163, $$164]) [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+                          project ([$$156, $$166, $$161, $$162, $$163, $$164]) [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                           -- STREAM_PROJECT  |PARTITIONED|
-                            exchange [cardinality: 5.0E12, op-cost: 0.0, total-cost: 2.600009E7]
+                            exchange [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 0.0, total-cost: 1.25003000009E12]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              join (eq($$176, $$177)) [cardinality: 5.0E12, op-cost: 1.4E7, total-cost: 2.600009E7]
+                              join (eq($$176, $$177)) [cardinality: 9.223372036854776E16, doc-size: 1.0, op-cost: 1.250004E12, total-cost: 1.25003000009E12]
                               -- HYBRID_HASH_JOIN [$$177][$$176]  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                                exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  assign [$$156] <- [$$ol.getField("ol_amount")] project: [$$156, $$166, $$161, $$162, $$163, $$177] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                  -- ASSIGN  |PARTITIONED|
-                                    unnest $$ol <- scan-collection($$179) project: [$$166, $$161, $$162, $$163, $$177, $$ol] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                    -- UNNEST  |PARTITIONED|
-                                      project ([$$166, $$161, $$162, $$163, $$177, $$179]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                                  project ([$$156, $$166, $$161, $$162, $$163, $$177]) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      join (and(eq($$166, $$170), eq($$171, $$172), eq($$173, $$174))) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 1.4E7, total-cost: 2.100009E7]
+                                      -- HYBRID_HASH_JOIN [$$170, $$172, $$174][$$166, $$171, $$173]  |PARTITIONED|
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          join (and(eq($$166, $$170), eq($$171, $$172), eq($$173, $$174))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                          -- HYBRID_HASH_JOIN [$$166, $$171, $$173][$$170, $$172, $$174]  |PARTITIONED|
-                                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                            -- HASH_PARTITION_EXCHANGE [$$166, $$171, $$173]  |PARTITIONED|
-                                              assign [$$177, $$163, $$162, $$161, $$173, $$171, $$166] <- [get-item(string-to-codepoint($$c.getField("c_state")), 0), $$c.getField("c_phone"), $$c.getField("c_city"), $$c.getField("c_last"), $$c.getField("c_w_id"), $$c.getField("c_d_id"), $$c.getField("c_id")] project: [$$166, $$161, $$162, $$163, $$177, $$171, $$173] [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 []<-[$$168, $$c] <- test.customer [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                                      exchange
-                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        empty-tuple-source
-                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                            -- HASH_PARTITION_EXCHANGE [$$170, $$172, $$174]  |PARTITIONED|
-                                              select (and(lt($$165, "2016-01-01 00:00:00.000000"), ge($$165, "2015-10-01 00:00:00.000000"))) project: [$$179, $$170, $$172, $$174] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          assign [$$156] <- [$$ol.getField("ol_amount")] project: [$$156, $$170, $$172, $$174] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- ASSIGN  |PARTITIONED|
+                                            unnest $$ol <- scan-collection($$179) project: [$$174, $$172, $$170, $$ol] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            -- UNNEST  |PARTITIONED|
+                                              select (and(lt($$165, "2016-01-01 00:00:00.000000"), ge($$165, "2015-10-01 00:00:00.000000"))) project: [$$174, $$172, $$170, $$179] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                               -- STREAM_SELECT  |PARTITIONED|
-                                                assign [$$174, $$172, $$170, $$165, $$179] <- [$$o.getField("o_w_id"), $$o.getField("o_d_id"), $$o.getField("o_c_id"), $$o.getField("o_entry_d"), $$o.getField("o_orderline")] project: [$$174, $$172, $$170, $$165, $$179] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                assign [$$174, $$172, $$170, $$165, $$179] <- [$$o.getField("o_w_id"), $$o.getField("o_d_id"), $$o.getField("o_c_id"), $$o.getField("o_entry_d"), $$o.getField("o_orderline")] project: [$$174, $$172, $$170, $$165, $$179] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                 -- ASSIGN  |PARTITIONED|
-                                                  project ([$$o]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  project ([$$o]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                   -- STREAM_PROJECT  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      data-scan []<-[$$169, $$o] <- test.orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                      data-scan []<-[$$169, $$o] <- test.orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- DATASOURCE_SCAN  |PARTITIONED|
-                                                        exchange
+                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          empty-tuple-source
+                                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                        -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                          assign [$$177, $$163, $$162, $$161, $$173, $$171, $$166] <- [get-item(string-to-codepoint($$c.getField("c_state")), 0), $$c.getField("c_phone"), $$c.getField("c_city"), $$c.getField("c_last"), $$c.getField("c_w_id"), $$c.getField("c_d_id"), $$c.getField("c_id")] project: [$$166, $$161, $$162, $$163, $$177, $$171, $$173] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- ASSIGN  |PARTITIONED|
+                                            project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            -- STREAM_PROJECT  |PARTITIONED|
+                                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                data-scan []<-[$$168, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- DATASOURCE_SCAN  |PARTITIONED|
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                 -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                  assign [$$164, $$176] <- [$$n.getField("n_name"), $$n.getField("n_nationkey")] project: [$$164, $$176] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                  assign [$$164, $$176] <- [$$n.getField("n_name"), $$n.getField("n_nationkey")] project: [$$164, $$176] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                   -- ASSIGN  |PARTITIONED|
-                                    project ([$$n]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    project ([$$n]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                     -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        data-scan []<-[$$167, $$n] <- test.nation [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                        data-scan []<-[$$167, $$n] <- test.nation [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                         -- DATASOURCE_SCAN  |PARTITIONED|
-                                          exchange
+                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            empty-tuple-source
+                                            empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
index 3846846..cdead55 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q18.plan
@@ -1,82 +1,82 @@
-distribute result [$$169] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+distribute result [$$169] [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+  exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    limit 100 [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+    limit 100 [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
     -- STREAM_LIMIT  |UNPARTITIONED|
-      assign [$$169] <- [{"c_last": $$c_last, "o_id": $$c_id, "o_entry_d": $$o_entry_d, "o_ol_cnt": $$o_ol_cnt, "$1": $$192}] project: [$$169] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+      assign [$$169] <- [{"c_last": $$c_last, "o_id": $$c_id, "o_entry_d": $$o_entry_d, "o_ol_cnt": $$o_ol_cnt, "$1": $$192}] project: [$$169] [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
       -- ASSIGN  |PARTITIONED|
-        project ([$$c_last, $$c_id, $$o_entry_d, $$o_ol_cnt, $$192]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+        project ([$$c_last, $$c_id, $$o_entry_d, $$o_ol_cnt, $$192]) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
         -- STREAM_PROJECT  |PARTITIONED|
-          exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+          exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
           -- SORT_MERGE_EXCHANGE [$$193(DESC), $$o_entry_d(ASC) ]  |PARTITIONED|
-            limit 100 [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+            limit 100 [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
             -- STREAM_LIMIT  |PARTITIONED|
-              exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+              exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                order (topK: 100) (DESC, $$193) (ASC, $$o_entry_d) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                order (topK: 100) (DESC, $$193) (ASC, $$o_entry_d) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                 -- STABLE_SORT [topK: 100] [$$193(DESC), $$o_entry_d(ASC)]  |PARTITIONED|
-                  exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                  exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    select (gt($$191, 200)) project: [$$c_last, $$c_id, $$o_entry_d, $$o_ol_cnt, $$192, $$193]
+                    select (gt($$191, 200)) project: [$$c_last, $$c_id, $$o_entry_d, $$o_ol_cnt, $$192, $$193] [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                     -- STREAM_SELECT  |PARTITIONED|
-                      project ([$$191, $$192, $$193, $$c_id, $$c_last, $$o_entry_d, $$o_ol_cnt]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                      project ([$$191, $$192, $$193, $$c_id, $$c_last, $$o_entry_d, $$o_ol_cnt]) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                       -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                        exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                           group by ([$$o_id := $$201; $$o_w_id := $$202; $$o_d_id := $$203; $$c_id := $$204; $$c_last := $$205; $$o_entry_d := $$206; $$o_ol_cnt := $$207]) decor ([]) {
-                                    aggregate [$$191, $$192, $$193] <- [agg-global-sql-sum($$198), agg-global-sql-sum($$199), agg-global-sql-sum($$200)]
+                                    aggregate [$$191, $$192, $$193] <- [agg-global-sql-sum($$198), agg-global-sql-sum($$199), agg-global-sql-sum($$200)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- AGGREGATE  |LOCAL|
-                                      nested tuple source
+                                      nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                 } [cardinality: 0.0, op-cost: 0.0, total-cost: 6000000.0]
+                                 } [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                           -- SORT_GROUP_BY[$$201, $$202, $$203, $$204, $$205, $$206, $$207]  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                            exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                             -- HASH_PARTITION_EXCHANGE [$$201, $$202, $$203, $$204, $$205, $$206, $$207]  |PARTITIONED|
                               group by ([$$201 := $$175; $$202 := $$183; $$203 := $$184; $$204 := $$185; $$205 := $$179; $$206 := $$180; $$207 := $$181]) decor ([]) {
-                                        aggregate [$$198, $$199, $$200] <- [agg-local-sql-sum($$160), agg-local-sql-sum($$160), agg-local-sql-sum($$160)]
+                                        aggregate [$$198, $$199, $$200] <- [agg-local-sql-sum($$160), agg-local-sql-sum($$160), agg-local-sql-sum($$160)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                         -- AGGREGATE  |LOCAL|
-                                          nested tuple source
+                                          nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                     } [cardinality: 0.0, op-cost: 0.0, total-cost: 6000000.0]
+                                     } [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                               -- SORT_GROUP_BY[$$175, $$183, $$184, $$185, $$179, $$180, $$181]  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                                exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  assign [$$160] <- [$$ol.getField("ol_amount")] project: [$$160, $$175, $$183, $$184, $$185, $$179, $$180, $$181] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                  -- ASSIGN  |PARTITIONED|
-                                    unnest $$ol <- scan-collection($$194) project: [$$175, $$183, $$184, $$180, $$181, $$185, $$179, $$ol] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                    -- UNNEST  |PARTITIONED|
-                                      project ([$$175, $$183, $$184, $$180, $$181, $$194, $$185, $$179]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+                                  project ([$$160, $$175, $$183, $$184, $$185, $$179, $$180, $$181]) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
+                                  -- STREAM_PROJECT  |PARTITIONED|
+                                    exchange [cardinality: 1.25E12, doc-size: 2.0, op-cost: 0.0, total-cost: 2.100009E7]
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      join (and(eq($$185, $$188), eq($$189, $$183), eq($$190, $$184))) [cardinality: 1.25E12, doc-size: 2.0, op-cost: 1.4E7, total-cost: 2.100009E7]
+                                      -- HYBRID_HASH_JOIN [$$188, $$183, $$184][$$185, $$189, $$190]  |PARTITIONED|
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          join (and(eq($$185, $$188), eq($$189, $$183), eq($$190, $$184))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                          -- HYBRID_HASH_JOIN [$$188, $$183, $$184][$$185, $$189, $$190]  |PARTITIONED|
-                                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                            -- HASH_PARTITION_EXCHANGE [$$188, $$183, $$184]  |PARTITIONED|
-                                              assign [$$181, $$180, $$175, $$188, $$183, $$184, $$194] <- [$$o.getField("o_ol_cnt"), $$o.getField("o_entry_d"), $$o.getField("o_id"), $$o.getField("o_c_id"), $$o.getField("o_w_id"), $$o.getField("o_d_id"), $$o.getField("o_orderline")] project: [$$175, $$183, $$184, $$180, $$181, $$194, $$188] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          assign [$$160] <- [$$ol.getField("ol_amount")] project: [$$160, $$175, $$183, $$184, $$180, $$181, $$188] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- ASSIGN  |PARTITIONED|
+                                            unnest $$ol <- scan-collection($$194) project: [$$181, $$180, $$175, $$188, $$183, $$184, $$ol] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            -- UNNEST  |PARTITIONED|
+                                              assign [$$181, $$180, $$175, $$188, $$183, $$184, $$194] <- [$$o.getField("o_ol_cnt"), $$o.getField("o_entry_d"), $$o.getField("o_id"), $$o.getField("o_c_id"), $$o.getField("o_w_id"), $$o.getField("o_d_id"), $$o.getField("o_orderline")] project: [$$181, $$180, $$175, $$188, $$183, $$184, $$194] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                               -- ASSIGN  |PARTITIONED|
-                                                project ([$$o]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                project ([$$o]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                 -- STREAM_PROJECT  |PARTITIONED|
-                                                  exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    data-scan []<-[$$186, $$o] <- test.orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                    data-scan []<-[$$186, $$o] <- test.orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- DATASOURCE_SCAN  |PARTITIONED|
-                                                      exchange
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        empty-tuple-source
+                                                        empty-tuple-source [cardinality: 0.0, doc-size: 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 [$$185, $$189, $$190]  |PARTITIONED|
-                                              assign [$$179, $$190, $$189, $$185] <- [$$c.getField("c_last"), $$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id")] project: [$$185, $$179, $$189, $$190] [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]
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                        -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                          assign [$$179, $$190, $$189, $$185] <- [$$c.getField("c_last"), $$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id")] project: [$$185, $$179, $$189, $$190] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- ASSIGN  |PARTITIONED|
+                                            project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            -- STREAM_PROJECT  |PARTITIONED|
+                                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                data-scan []<-[$$187, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- DATASOURCE_SCAN  |PARTITIONED|
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    data-scan []<-[$$187, $$c] <- test.customer [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                                      exchange
-                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        empty-tuple-source
-                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q21.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q21.plan
index 2a00f54..fb3ad13 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q21.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q21.plan
@@ -1,192 +1,192 @@
-distribute result [$$339] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+distribute result [$$339] [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+  exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    limit 100 [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+    limit 100 [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
     -- STREAM_LIMIT  |UNPARTITIONED|
-      project ([$$339]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+      project ([$$339]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+        exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
         -- SORT_MERGE_EXCHANGE [$$su_name(ASC) ]  |PARTITIONED|
-          assign [$$339] <- [{"su_name": $$su_name, "numwait": $$364}] project: [$$su_name, $$339] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+          assign [$$339] <- [{"su_name": $$su_name, "numwait": $$364}] project: [$$su_name, $$339] [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
           -- ASSIGN  |PARTITIONED|
-            limit 100 [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+            limit 100 [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
             -- STREAM_LIMIT  |PARTITIONED|
-              exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                 group by ([$$su_name := $$399]) decor ([]) {
-                          aggregate [$$364] <- [agg-sql-sum($$398)]
+                          aggregate [$$364] <- [agg-sql-sum($$398)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- AGGREGATE  |LOCAL|
-                            nested tuple source
+                            nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                       } [cardinality: 0.0, op-cost: 0.0, total-cost: 1.250023E12]
+                       } [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                 -- SORT_GROUP_BY[$$399]  |PARTITIONED|
-                  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                  exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                   -- HASH_PARTITION_EXCHANGE [$$399]  |PARTITIONED|
                     group by ([$$399 := $$su_name]) decor ([]) {
-                              aggregate [$$398] <- [agg-sql-count(1)]
+                              aggregate [$$398] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- AGGREGATE  |LOCAL|
-                                nested tuple source
+                                nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- NESTED_TUPLE_SOURCE  |LOCAL|
-                           } [cardinality: 0.0, op-cost: 0.0, total-cost: 1.250023E12]
+                           } [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                     -- SORT_GROUP_BY[$$su_name]  |PARTITIONED|
-                      exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                      exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        select (eq($$363, 0)) project: [$$su_name]
+                        select (eq($$363, 0)) project: [$$su_name] [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                         -- STREAM_SELECT  |PARTITIONED|
-                          project ([$$363, $$su_name]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                          project ([$$363, $$su_name]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                           -- STREAM_PROJECT  |PARTITIONED|
-                            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                            exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                               group by ([$$o_w_id := $$390; $$o_d_id := $$391; $$o_id := $$392; $$n_nationkey := $$393; $$su_suppkey := $$394; $$s_w_id := $$395; $$s_i_id := $$396; $$su_name := $$397]) decor ([]) {
-                                        aggregate [$$363] <- [agg-sql-sum($$389)]
+                                        aggregate [$$363] <- [agg-sql-sum($$389)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                         -- AGGREGATE  |LOCAL|
-                                          nested tuple source
+                                          nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                     } [cardinality: 0.0, op-cost: 0.0, total-cost: 1.250023E12]
+                                     } [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                               -- SORT_GROUP_BY[$$390, $$391, $$392, $$393, $$394, $$395, $$396, $$397]  |PARTITIONED|
-                                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                                exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                 -- HASH_PARTITION_EXCHANGE [$$390, $$391, $$392, $$393, $$394, $$395, $$396, $$397]  |PARTITIONED|
                                   group by ([$$390 := $$352; $$391 := $$378; $$392 := $$377; $$393 := $$354; $$394 := $$355; $$395 := $$351; $$396 := $$350; $$397 := $$379]) decor ([]) {
-                                            aggregate [$$389] <- [agg-sql-count($$326)]
+                                            aggregate [$$389] <- [agg-sql-count($$326)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- AGGREGATE  |LOCAL|
-                                              nested tuple source
+                                              nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                         } [cardinality: 0.0, op-cost: 0.0, total-cost: 1.250023E12]
+                                         } [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                   -- SORT_GROUP_BY[$$352, $$378, $$377, $$354, $$355, $$351, $$350, $$379]  |PARTITIONED|
-                                    exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                                    exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      project ([$$326, $$352, $$378, $$377, $$354, $$355, $$351, $$350, $$379]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                                      project ([$$326, $$352, $$378, $$377, $$354, $$355, $$351, $$350, $$379]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                       -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 1.250023E12]
+                                        exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          join (eq($$365, $$354)) [cardinality: 9.223372036854776E16, op-cost: 2.50004E11, total-cost: 1.250023E12]
+                                          join (eq($$365, $$354)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                                           -- HYBRID_HASH_JOIN [$$365][$$354]  |PARTITIONED|
-                                            exchange [cardinality: 2.5E11, op-cost: 0.0, total-cost: 1.000014E12]
+                                            exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 1.5626062524E16]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              project ([$$326, $$352, $$378, $$377, $$355, $$351, $$350, $$379, $$365]) [cardinality: 2.5E11, op-cost: 0.0, total-cost: 1.000014E12]
+                                              project ([$$326, $$352, $$378, $$377, $$355, $$351, $$350, $$379, $$365]) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 1.5626062524E16]
                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                exchange [cardinality: 2.5E11, op-cost: 0.0, total-cost: 1.000014E12]
+                                                exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 1.5626062524E16]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (eq($$366, $$355)) [cardinality: 2.5E11, op-cost: 1500000.0, total-cost: 1.000014E12]
+                                                  join (eq($$366, $$355)) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 1.5625000004E16, total-cost: 1.5626062524E16]
                                                   -- HYBRID_HASH_JOIN [$$366][$$355]  |PARTITIONED|
-                                                    exchange [cardinality: 500000.0, op-cost: 500000.0, total-cost: 1.0000105E12]
-                                                    -- HASH_PARTITION_EXCHANGE [$$366]  |PARTITIONED|
-                                                      project ([$$326, $$352, $$378, $$377, $$351, $$350, $$366]) [cardinality: 500000.0, op-cost: 0.0, total-cost: 1.00001E12]
-                                                      -- STREAM_PROJECT  |PARTITIONED|
-                                                        exchange [cardinality: 500000.0, op-cost: 500000.0, total-cost: 1.0000105E12]
-                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          join (and(eq($$352, $$351), eq($$362, $$350))) [cardinality: 500000.0, op-cost: 1500000.0, total-cost: 1.00001E12]
-                                                          -- HYBRID_HASH_JOIN [$$352, $$362][$$351, $$350]  |PARTITIONED|
-                                                            exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                            -- HASH_PARTITION_EXCHANGE [$$352, $$362]  |PARTITIONED|
-                                                              project ([$$326, $$352, $$378, $$377, $$362]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                              -- STREAM_PROJECT  |PARTITIONED|
-                                                                exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  left outer join (and(eq($$383, $$378), gt($$384, $$353), eq($$381, $$377), eq($$382, $$352))) [cardinality: 500000.0, op-cost: 1.0E12, total-cost: 1.000006E12]
-                                                                  -- HYBRID_HASH_JOIN [$$378, $$377, $$352][$$383, $$381, $$382]  |PARTITIONED|
-                                                                    exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                    -- HASH_PARTITION_EXCHANGE [$$378, $$377, $$352]  |PARTITIONED|
-                                                                      select (gt($$353, string(numeric-add(date($$349), duration: {P150D })))) project: [$$352, $$378, $$377, $$362, $$353] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                      -- STREAM_SELECT  |PARTITIONED|
-                                                                        assign [$$362, $$353] <- [$$ol1.getField("ol_i_id"), $$ol1.getField("ol_delivery_d")] project: [$$378, $$377, $$352, $$349, $$362, $$353] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                        -- ASSIGN  |PARTITIONED|
-                                                                          unnest $$ol1 <- scan-collection($$376) project: [$$378, $$377, $$352, $$349, $$ol1] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                          -- UNNEST  |PARTITIONED|
-                                                                            select (and(le($$349, "2017-12-31 00:00:00"), ge($$349, "2017-12-01 00:00:00")))
-                                                                            -- STREAM_SELECT  |PARTITIONED|
-                                                                              assign [$$378, $$377, $$352, $$349, $$376] <- [$$o1.getField("o_d_id"), $$o1.getField("o_id"), $$o1.getField("o_w_id"), $$o1.getField("o_entry_d"), $$o1.getField("o_orderline")] project: [$$378, $$377, $$352, $$349, $$376] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                              -- ASSIGN  |PARTITIONED|
-                                                                                assign [$$o1] <- [$$o2] project: [$$o1] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                -- ASSIGN  |PARTITIONED|
-                                                                                  exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                    replicate [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                    -- REPLICATE  |PARTITIONED|
-                                                                                      exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                        project ([$$o2]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                        -- STREAM_PROJECT  |PARTITIONED|
-                                                                                          exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                            data-scan []<-[$$361, $$o2] <- test.orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                                                            -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                              exchange
-                                                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                                empty-tuple-source
-                                                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                    exchange
-                                                                    -- HASH_PARTITION_EXCHANGE [$$383, $$381, $$382]  |PARTITIONED|
-                                                                      assign [$$326] <- [{"o_id": $$381, "o_w_id": $$382, "o_d_id": $$383, "ol_delivery_d": $$384}.getField("o_id")]
-                                                                      -- ASSIGN  |PARTITIONED|
-                                                                        assign [$$384] <- [$$ol2.getField("ol_delivery_d")] project: [$$383, $$382, $$381, $$384]
-                                                                        -- ASSIGN  |PARTITIONED|
-                                                                          unnest $$ol2 <- scan-collection($$380) project: [$$383, $$382, $$381, $$ol2] [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                                          -- UNNEST  |PARTITIONED|
-                                                                            select (and(le($$356, "2017-12-31 00:00:00"), ge($$356, "2017-12-01 00:00:00"))) project: [$$383, $$382, $$381, $$380]
-                                                                            -- STREAM_SELECT  |PARTITIONED|
-                                                                              assign [$$383, $$382, $$381, $$356, $$380] <- [$$o2.getField("o_d_id"), $$o2.getField("o_w_id"), $$o2.getField("o_id"), $$o2.getField("o_entry_d"), $$o2.getField("o_orderline")] project: [$$383, $$382, $$381, $$356, $$380]
-                                                                              -- ASSIGN  |PARTITIONED|
-                                                                                exchange
-                                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                  replicate [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                  -- REPLICATE  |PARTITIONED|
-                                                                                    exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                      project ([$$o2]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                      -- STREAM_PROJECT  |PARTITIONED|
-                                                                                        exchange [cardinality: 1000000.0, op-cost: 500000.0, total-cost: 1500000.0]
-                                                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                          data-scan []<-[$$361, $$o2] <- test.orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                            exchange
-                                                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                              empty-tuple-source
-                                                                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                                            -- HASH_PARTITION_EXCHANGE [$$351, $$350]  |PARTITIONED|
-                                                              assign [$$366] <- [numeric-mod(numeric-multiply($$351, $$350), 10000)] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                              -- ASSIGN  |PARTITIONED|
-                                                                assign [$$351, $$350] <- [$$s.getField("s_w_id"), $$s.getField("s_i_id")] project: [$$351, $$350] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                -- ASSIGN  |PARTITIONED|
-                                                                  project ([$$s]) [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 []<-[$$359, $$s] <- test.stock [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                                      -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                        exchange
-                                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          empty-tuple-source
-                                                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                                    -- HASH_PARTITION_EXCHANGE [$$355]  |PARTITIONED|
-                                                      assign [$$379, $$355, $$365] <- [$$su.getField("su_name"), $$su.getField("su_suppkey"), $$su.getField("su_nationkey")] project: [$$355, $$379, $$365] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                      -- ASSIGN  |PARTITIONED|
-                                                        project ([$$su]) [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 []<-[$$358, $$su] <- test.supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                            -- DATASOURCE_SCAN  |PARTITIONED|
-                                                              exchange
-                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                empty-tuple-source
-                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                            exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                            -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                              select (eq($$n.getField("n_name"), "Peru")) project: [$$354] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                              -- STREAM_SELECT  |PARTITIONED|
-                                                assign [$$354] <- [$$n.getField("n_nationkey")] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                -- ASSIGN  |PARTITIONED|
-                                                  project ([$$n]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                  -- STREAM_PROJECT  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                                                    exchange [cardinality: 1.5625E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.062515E12]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      data-scan []<-[$$357, $$n] <- test.nation [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                      -- DATASOURCE_SCAN  |PARTITIONED|
-                                                        exchange
+                                                      project ([$$326, $$352, $$378, $$377, $$351, $$350, $$366]) [cardinality: 1.5625E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.062515E12]
+                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                        exchange [cardinality: 1.5625E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.062515E12]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          empty-tuple-source
+                                                          join (and(eq($$352, $$351), eq($$362, $$350))) [cardinality: 1.5625E16, doc-size: -3.0, op-cost: 6.2504E10, total-cost: 1.062515E12]
+                                                          -- HYBRID_HASH_JOIN [$$352, $$362][$$351, $$350]  |PARTITIONED|
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              project ([$$326, $$352, $$378, $$377, $$362]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                              -- STREAM_PROJECT  |PARTITIONED|
+                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                  left outer join (and(eq($$383, $$378), gt($$384, $$353), eq($$381, $$377), eq($$382, $$352))) [cardinality: 6.25E10, doc-size: -2.0, op-cost: 1.0E12, total-cost: 1.000006E12]
+                                                                  -- HYBRID_HASH_JOIN [$$378, $$377, $$352][$$383, $$381, $$382]  |PARTITIONED|
+                                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                    -- HASH_PARTITION_EXCHANGE [$$378, $$377, $$352]  |PARTITIONED|
+                                                                      select (gt($$353, string(numeric-add(date($$349), duration: {P150D })))) project: [$$352, $$378, $$377, $$362, $$353] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                      -- STREAM_SELECT  |PARTITIONED|
+                                                                        assign [$$362, $$353] <- [$$ol1.getField("ol_i_id"), $$ol1.getField("ol_delivery_d")] project: [$$378, $$377, $$352, $$349, $$362, $$353] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                        -- ASSIGN  |PARTITIONED|
+                                                                          unnest $$ol1 <- scan-collection($$376) project: [$$378, $$377, $$352, $$349, $$ol1] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                          -- UNNEST  |PARTITIONED|
+                                                                            select (and(le($$349, "2017-12-31 00:00:00"), ge($$349, "2017-12-01 00:00:00"))) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                            -- STREAM_SELECT  |PARTITIONED|
+                                                                              assign [$$378, $$377, $$352, $$349, $$376] <- [$$o1.getField("o_d_id"), $$o1.getField("o_id"), $$o1.getField("o_w_id"), $$o1.getField("o_entry_d"), $$o1.getField("o_orderline")] project: [$$378, $$377, $$352, $$349, $$376] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                              -- ASSIGN  |PARTITIONED|
+                                                                                assign [$$o1] <- [$$o2] project: [$$o1] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                -- ASSIGN  |PARTITIONED|
+                                                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                    replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                    -- REPLICATE  |PARTITIONED|
+                                                                                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                        project ([$$o2]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                        -- STREAM_PROJECT  |PARTITIONED|
+                                                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                            data-scan []<-[$$361, $$o2] <- test.orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                            -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                    -- HASH_PARTITION_EXCHANGE [$$383, $$381, $$382]  |PARTITIONED|
+                                                                      assign [$$326] <- [{"o_id": $$381, "o_w_id": $$382, "o_d_id": $$383, "ol_delivery_d": $$384}.getField("o_id")] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                      -- ASSIGN  |PARTITIONED|
+                                                                        assign [$$384] <- [$$ol2.getField("ol_delivery_d")] project: [$$383, $$382, $$381, $$384] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                        -- ASSIGN  |PARTITIONED|
+                                                                          unnest $$ol2 <- scan-collection($$380) project: [$$383, $$382, $$381, $$ol2] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                                          -- UNNEST  |PARTITIONED|
+                                                                            select (and(le($$356, "2017-12-31 00:00:00"), ge($$356, "2017-12-01 00:00:00"))) project: [$$383, $$382, $$381, $$380] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                            -- STREAM_SELECT  |PARTITIONED|
+                                                                              assign [$$383, $$382, $$381, $$356, $$380] <- [$$o2.getField("o_d_id"), $$o2.getField("o_w_id"), $$o2.getField("o_id"), $$o2.getField("o_entry_d"), $$o2.getField("o_orderline")] project: [$$383, $$382, $$381, $$356, $$380] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                              -- ASSIGN  |PARTITIONED|
+                                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                  replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                  -- REPLICATE  |PARTITIONED|
+                                                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                      project ([$$o2]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                          data-scan []<-[$$361, $$o2] <- test.orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                          -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                              assign [$$366] <- [numeric-mod(numeric-multiply($$351, $$350), 10000)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                              -- ASSIGN  |PARTITIONED|
+                                                                assign [$$351, $$350] <- [$$s.getField("s_w_id"), $$s.getField("s_i_id")] project: [$$351, $$350] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                -- ASSIGN  |PARTITIONED|
+                                                                  project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                  -- STREAM_PROJECT  |PARTITIONED|
+                                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                      data-scan []<-[$$359, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                      -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                      assign [$$379, $$355, $$365] <- [$$su.getField("su_name"), $$su.getField("su_suppkey"), $$su.getField("su_nationkey")] project: [$$355, $$379, $$365] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      -- ASSIGN  |PARTITIONED|
+                                                        project ([$$su]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        -- STREAM_PROJECT  |PARTITIONED|
+                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                            data-scan []<-[$$358, $$su] <- test.supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            -- DATASOURCE_SCAN  |PARTITIONED|
+                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                              select (eq($$n.getField("n_name"), "Peru")) project: [$$354] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- STREAM_SELECT  |PARTITIONED|
+                                                assign [$$354] <- [$$n.getField("n_nationkey")] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- ASSIGN  |PARTITIONED|
+                                                  project ([$$n]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  -- STREAM_PROJECT  |PARTITIONED|
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                      data-scan []<-[$$357, $$n] <- test.nation [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      -- DATASOURCE_SCAN  |PARTITIONED|
+                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q5.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q5.plan
index a1f1fce..c8fccb6 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q5.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q5.plan
@@ -38,57 +38,43 @@
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                             join (eq($$256, $$257)) [cardinality: 9.223372036854776E16, doc-size: -6.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                             -- HYBRID_HASH_JOIN [$$256][$$257]  |PARTITIONED|
-                              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 2.50025E11]
+                              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                project ([$$280, $$275, $$256]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 2.50025E11]
+                                project ([$$280, $$275, $$256]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                 -- STREAM_PROJECT  |PARTITIONED|
-                                  exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 2.50025E11]
+                                  exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    join (eq($$266, $$274)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 2.50004E11, total-cost: 2.50025E11]
+                                    join (eq($$266, $$274)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                                     -- HYBRID_HASH_JOIN [$$266][$$274]  |PARTITIONED|
-                                      exchange [cardinality: 2.5E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                      exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        project ([$$280, $$266]) [cardinality: 2.5E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                        project ([$$280, $$266]) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                         -- STREAM_PROJECT  |PARTITIONED|
-                                          exchange [cardinality: 2.5E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                          exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            join (and(eq($$290, $$269), eq($$266, $$258))) [cardinality: 2.5E11, doc-size: -4.0, op-cost: 2000000.0, total-cost: 1.6E7]
+                                            join (and(eq($$290, $$269), eq($$266, $$258))) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 3.1250000004E16, total-cost: 3.1250125024E16]
                                             -- HYBRID_HASH_JOIN [$$290, $$258][$$269, $$266]  |PARTITIONED|
-                                              exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
-                                              -- HASH_PARTITION_EXCHANGE [$$290, $$258]  |PARTITIONED|
-                                                assign [$$290] <- [numeric-mod(numeric-multiply($$245, $$246), 10000)] project: [$$280, $$290, $$258] [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                              exchange [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                assign [$$290] <- [numeric-mod(numeric-multiply($$245, $$246), 10000)] project: [$$280, $$290, $$258] [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                                 -- ASSIGN  |PARTITIONED|
-                                                  project ([$$280, $$245, $$246, $$258]) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                                  project ([$$280, $$258, $$245, $$246]) [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                                   -- STREAM_PROJECT  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                                    exchange [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      join (and(eq($$276, $$260), eq($$277, $$254), eq($$278, $$263))) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
-                                                      -- HYBRID_HASH_JOIN [$$260, $$254, $$263][$$276, $$277, $$278]  |PARTITIONED|
-                                                        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
-                                                        -- HASH_PARTITION_EXCHANGE [$$260, $$254, $$263]  |PARTITIONED|
-                                                          project ([$$280, $$245, $$246, $$260, $$254, $$263]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                      join (and(eq($$254, $$245), eq($$281, $$246))) [cardinality: 3.125E16, doc-size: -3.0, op-cost: 1.25004E11, total-cost: 1.25015E11]
+                                                      -- HYBRID_HASH_JOIN [$$254, $$281][$$245, $$246]  |PARTITIONED|
+                                                        exchange [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                          project ([$$280, $$258, $$254, $$281]) [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                           -- STREAM_PROJECT  |PARTITIONED|
-                                                            exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                            exchange [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              join (and(eq($$254, $$245), eq($$281, $$246))) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                                              -- HYBRID_HASH_JOIN [$$245, $$246][$$254, $$281]  |PARTITIONED|
+                                                              join (and(eq($$276, $$260), eq($$277, $$254), eq($$278, $$263))) [cardinality: 1.25E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                              -- HYBRID_HASH_JOIN [$$260, $$254, $$263][$$276, $$277, $$278]  |PARTITIONED|
                                                                 exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                -- HASH_PARTITION_EXCHANGE [$$245, $$246]  |PARTITIONED|
-                                                                  assign [$$246, $$245] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$245, $$246] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                  -- ASSIGN  |PARTITIONED|
-                                                                    project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                    -- STREAM_PROJECT  |PARTITIONED|
-                                                                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        data-scan []<-[$$247, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                        -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                            empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                -- HASH_PARTITION_EXCHANGE [$$254, $$281]  |PARTITIONED|
-                                                                  assign [$$281, $$280] <- [$$ol.getField("ol_i_id"), $$ol.getField("ol_amount")] project: [$$280, $$260, $$254, $$263, $$281] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                -- HASH_PARTITION_EXCHANGE [$$260, $$254, $$263]  |PARTITIONED|
+                                                                  assign [$$281, $$280] <- [$$ol.getField("ol_i_id"), $$ol.getField("ol_amount")] project: [$$280, $$254, $$281, $$260, $$263] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                   -- ASSIGN  |PARTITIONED|
                                                                     unnest $$ol <- scan-collection($$271) project: [$$263, $$260, $$254, $$ol] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                     -- UNNEST  |PARTITIONED|
@@ -106,22 +92,36 @@
                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                   empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                -- HASH_PARTITION_EXCHANGE [$$276, $$277, $$278]  |PARTITIONED|
+                                                                  assign [$$258, $$278, $$277, $$276] <- [get-item(string-to-codepoint($$c.getField("c_state")), 0), $$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id")] project: [$$258, $$276, $$277, $$278] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                  -- ASSIGN  |PARTITIONED|
+                                                                    project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                    -- STREAM_PROJECT  |PARTITIONED|
+                                                                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                        data-scan []<-[$$249, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                        -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                            empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                            -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                         exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                        -- HASH_PARTITION_EXCHANGE [$$276, $$277, $$278]  |PARTITIONED|
-                                                          assign [$$258, $$278, $$277, $$276] <- [get-item(string-to-codepoint($$c.getField("c_state")), 0), $$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id")] project: [$$258, $$276, $$277, $$278] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                          assign [$$246, $$245] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$245, $$246] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- ASSIGN  |PARTITIONED|
-                                                            project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- STREAM_PROJECT  |PARTITIONED|
                                                               exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                data-scan []<-[$$249, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                data-scan []<-[$$247, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                 -- DATASOURCE_SCAN  |PARTITIONED|
                                                                   exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                     empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                               exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                              -- HASH_PARTITION_EXCHANGE [$$269, $$266]  |PARTITIONED|
+                                              -- BROADCAST_EXCHANGE  |PARTITIONED|
                                                 assign [$$269, $$266] <- [$$su.getField("su_suppkey"), $$su.getField("su_nationkey")] project: [$$266, $$269] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                 -- ASSIGN  |PARTITIONED|
                                                   project ([$$su]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q7.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q7.plan
index dfdff1f..a92ac52 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q7.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q7.plan
@@ -34,57 +34,43 @@
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                         join (eq($$288, $$304)) [cardinality: 9.223372036854776E16, doc-size: -6.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                         -- HYBRID_HASH_JOIN [$$288][$$304]  |PARTITIONED|
-                          exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 5.00025E11]
+                          exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            project ([$$313, $$277, $$309, $$285, $$288, $$286]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 5.00025E11]
+                            project ([$$313, $$277, $$309, $$285, $$288, $$286]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                             -- STREAM_PROJECT  |PARTITIONED|
-                              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 5.00025E11]
+                              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                join (eq($$277, $$303)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 5.00004E11, total-cost: 5.00025E11]
+                                join (eq($$277, $$303)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                                 -- HYBRID_HASH_JOIN [$$277][$$303]  |PARTITIONED|
-                                  exchange [cardinality: 5.0E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                  exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    project ([$$313, $$277, $$309, $$285, $$288]) [cardinality: 5.0E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                    project ([$$313, $$277, $$309, $$285, $$288]) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                     -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange [cardinality: 5.0E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                      exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        join (eq($$326, $$300)) [cardinality: 5.0E11, doc-size: -4.0, op-cost: 2000000.0, total-cost: 1.6E7]
+                                        join (eq($$326, $$300)) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 3.1250000004E16, total-cost: 3.1250125024E16]
                                         -- HYBRID_HASH_JOIN [$$326][$$300]  |PARTITIONED|
-                                          exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
-                                          -- HASH_PARTITION_EXCHANGE [$$326]  |PARTITIONED|
-                                            assign [$$326] <- [numeric-mod(numeric-multiply($$275, $$276), 10000)] project: [$$313, $$309, $$285, $$288, $$326] [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                          exchange [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            assign [$$326] <- [numeric-mod(numeric-multiply($$275, $$276), 10000)] project: [$$313, $$309, $$285, $$288, $$326] [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                             -- ASSIGN  |PARTITIONED|
-                                              project ([$$313, $$309, $$275, $$276, $$285, $$288]) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                              project ([$$313, $$309, $$285, $$288, $$275, $$276]) [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                                exchange [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (and(eq($$305, $$291), eq($$306, $$293), eq($$307, $$295))) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
-                                                  -- HYBRID_HASH_JOIN [$$291, $$293, $$295][$$305, $$306, $$307]  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
-                                                    -- HASH_PARTITION_EXCHANGE [$$291, $$293, $$295]  |PARTITIONED|
-                                                      project ([$$313, $$309, $$275, $$276, $$291, $$293, $$295]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                  join (and(eq($$310, $$275), eq($$311, $$276))) [cardinality: 3.125E16, doc-size: -3.0, op-cost: 1.25004E11, total-cost: 1.25015E11]
+                                                  -- HYBRID_HASH_JOIN [$$310, $$311][$$275, $$276]  |PARTITIONED|
+                                                    exchange [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                      project ([$$313, $$309, $$285, $$288, $$310, $$311]) [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                       -- STREAM_PROJECT  |PARTITIONED|
-                                                        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                        exchange [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          join (and(eq($$310, $$275), eq($$311, $$276))) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                                          -- HYBRID_HASH_JOIN [$$275, $$276][$$310, $$311]  |PARTITIONED|
+                                                          join (and(eq($$305, $$291), eq($$306, $$293), eq($$307, $$295))) [cardinality: 1.25E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                          -- HYBRID_HASH_JOIN [$$291, $$293, $$295][$$305, $$306, $$307]  |PARTITIONED|
                                                             exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                            -- HASH_PARTITION_EXCHANGE [$$275, $$276]  |PARTITIONED|
-                                                              assign [$$276, $$275] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$275, $$276] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                              -- ASSIGN  |PARTITIONED|
-                                                                project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                -- STREAM_PROJECT  |PARTITIONED|
-                                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                    data-scan []<-[$$278, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                            -- HASH_PARTITION_EXCHANGE [$$310, $$311]  |PARTITIONED|
-                                                              select (and(ge($$284, "2017-01-01 00:00:00.000000"), le($$284, "2018-12-31 00:00:00.000000"))) project: [$$313, $$309, $$291, $$293, $$295, $$310, $$311] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            -- HASH_PARTITION_EXCHANGE [$$291, $$293, $$295]  |PARTITIONED|
+                                                              select (and(ge($$284, "2017-01-01 00:00:00.000000"), le($$284, "2018-12-31 00:00:00.000000"))) project: [$$313, $$309, $$310, $$311, $$291, $$293, $$295] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                               -- STREAM_SELECT  |PARTITIONED|
                                                                 assign [$$313, $$311, $$310, $$284] <- [$$ol.getField("ol_amount"), $$ol.getField("ol_i_id"), $$ol.getField("ol_supply_w_id"), $$ol.getField("ol_delivery_d")] project: [$$309, $$295, $$293, $$291, $$313, $$311, $$310, $$284] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                 -- ASSIGN  |PARTITIONED|
@@ -102,24 +88,38 @@
                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                               empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                    -- HASH_PARTITION_EXCHANGE [$$305, $$306, $$307]  |PARTITIONED|
-                                                      assign [$$288] <- [get-item(string-to-codepoint($$285), 0)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                      -- ASSIGN  |PARTITIONED|
-                                                        assign [$$307, $$306, $$305, $$285] <- [$$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id"), $$c.getField("c_state")] project: [$$307, $$306, $$305, $$285] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                        -- ASSIGN  |PARTITIONED|
-                                                          project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                          -- STREAM_PROJECT  |PARTITIONED|
                                                             exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              data-scan []<-[$$280, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                              -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                            -- HASH_PARTITION_EXCHANGE [$$305, $$306, $$307]  |PARTITIONED|
+                                                              assign [$$288] <- [get-item(string-to-codepoint($$285), 0)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                              -- ASSIGN  |PARTITIONED|
+                                                                assign [$$307, $$306, $$305, $$285] <- [$$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id"), $$c.getField("c_state")] project: [$$307, $$306, $$305, $$285] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                -- ASSIGN  |PARTITIONED|
+                                                                  project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                  -- STREAM_PROJECT  |PARTITIONED|
+                                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                      data-scan []<-[$$280, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                      -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                      assign [$$276, $$275] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$275, $$276] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      -- ASSIGN  |PARTITIONED|
+                                                        project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        -- STREAM_PROJECT  |PARTITIONED|
+                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                            data-scan []<-[$$278, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            -- DATASOURCE_SCAN  |PARTITIONED|
+                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                           exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                          -- HASH_PARTITION_EXCHANGE [$$300]  |PARTITIONED|
+                                          -- BROADCAST_EXCHANGE  |PARTITIONED|
                                             assign [$$300, $$277] <- [$$su.getField("su_suppkey"), $$su.getField("su_nationkey")] project: [$$277, $$300] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                             -- ASSIGN  |PARTITIONED|
                                               project ([$$su]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q8.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q8.plan
index 0b94e96..de34917 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q8.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q8.plan
@@ -50,56 +50,40 @@
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                         join (eq($$308, $$309)) [cardinality: 9.223372036854776E16, doc-size: -6.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                                         -- HYBRID_HASH_JOIN [$$308][$$309]  |PARTITIONED|
-                                          exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 5.00025E11]
+                                          exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            project ([$$335, $$305, $$295, $$296, $$308]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 5.00025E11]
+                                            project ([$$335, $$305, $$295, $$296, $$308]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                             -- STREAM_PROJECT  |PARTITIONED|
-                                              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 5.00025E11]
+                                              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                join (eq($$331, $$311)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 5.00004E11, total-cost: 5.00025E11]
+                                                join (eq($$331, $$311)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                                                 -- HYBRID_HASH_JOIN [$$311][$$331]  |PARTITIONED|
-                                                  exchange [cardinality: 5.0E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                                  exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    project ([$$335, $$305, $$295, $$296, $$311]) [cardinality: 5.0E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                                    project ([$$335, $$305, $$295, $$296, $$311]) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                                     -- STREAM_PROJECT  |PARTITIONED|
-                                                      exchange [cardinality: 5.0E11, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                                      exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 3.1250125024E16]
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        join (eq($$324, $$306)) [cardinality: 5.0E11, doc-size: -4.0, op-cost: 2000000.0, total-cost: 1.6E7]
+                                                        join (eq($$324, $$306)) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 3.1250000004E16, total-cost: 3.1250125024E16]
                                                         -- HYBRID_HASH_JOIN [$$306][$$324]  |PARTITIONED|
-                                                          exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
-                                                          -- HASH_PARTITION_EXCHANGE [$$306]  |PARTITIONED|
-                                                            project ([$$335, $$305, $$295, $$296, $$311, $$306]) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                                          exchange [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
+                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                            project ([$$335, $$305, $$295, $$296, $$311, $$306]) [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                                             -- STREAM_PROJECT  |PARTITIONED|
-                                                              exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                                              exchange [cardinality: 3.125E16, doc-size: -3.0, op-cost: 0.0, total-cost: 1.25015E11]
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                join (and(eq($$333, $$313), eq($$334, $$315), eq($$332, $$317))) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
-                                                                -- HYBRID_HASH_JOIN [$$313, $$315, $$317][$$333, $$334, $$332]  |PARTITIONED|
-                                                                  exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
-                                                                  -- HASH_PARTITION_EXCHANGE [$$313, $$315, $$317]  |PARTITIONED|
-                                                                    project ([$$335, $$305, $$295, $$296, $$306, $$313, $$315, $$317]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                                join (and(eq($$306, $$296), eq($$336, $$295))) [cardinality: 3.125E16, doc-size: -3.0, op-cost: 1.25004E11, total-cost: 1.25015E11]
+                                                                -- HYBRID_HASH_JOIN [$$306, $$336][$$296, $$295]  |PARTITIONED|
+                                                                  exchange [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                    project ([$$335, $$305, $$311, $$306, $$336]) [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                                     -- STREAM_PROJECT  |PARTITIONED|
-                                                                      exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                                      exchange [cardinality: 1.25E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                        join (and(eq($$306, $$296), eq($$336, $$295))) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                                                        -- HYBRID_HASH_JOIN [$$296, $$295][$$306, $$336]  |PARTITIONED|
+                                                                        join (and(eq($$333, $$313), eq($$334, $$315), eq($$332, $$317))) [cardinality: 1.25E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                                        -- HYBRID_HASH_JOIN [$$313, $$315, $$317][$$333, $$334, $$332]  |PARTITIONED|
                                                                           exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                          -- HASH_PARTITION_EXCHANGE [$$296, $$295]  |PARTITIONED|
-                                                                            select (lt($$296, 1000)) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                            -- STREAM_SELECT  |PARTITIONED|
-                                                                              assign [$$296, $$295] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$296, $$295] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                              -- ASSIGN  |PARTITIONED|
-                                                                                project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                -- STREAM_PROJECT  |PARTITIONED|
-                                                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                    data-scan []<-[$$297, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                          -- HASH_PARTITION_EXCHANGE [$$306, $$336]  |PARTITIONED|
+                                                                          -- HASH_PARTITION_EXCHANGE [$$313, $$315, $$317]  |PARTITIONED|
                                                                             select (lt($$306, 1000)) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                             -- STREAM_SELECT  |PARTITIONED|
                                                                               assign [$$336, $$335, $$306] <- [$$ol.getField("ol_supply_w_id"), $$ol.getField("ol_amount"), $$ol.getField("ol_i_id")] project: [$$317, $$315, $$313, $$305, $$336, $$335, $$306] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
@@ -120,22 +104,38 @@
                                                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                                               empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                          -- HASH_PARTITION_EXCHANGE [$$333, $$334, $$332]  |PARTITIONED|
+                                                                            assign [$$311, $$334, $$333, $$332] <- [get-item(string-to-codepoint($$c.getField("c_state")), 0), $$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id")] project: [$$311, $$333, $$334, $$332] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                            -- ASSIGN  |PARTITIONED|
+                                                                              project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                              -- STREAM_PROJECT  |PARTITIONED|
+                                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                  data-scan []<-[$$300, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                                  -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                                   exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                  -- HASH_PARTITION_EXCHANGE [$$333, $$334, $$332]  |PARTITIONED|
-                                                                    assign [$$311, $$334, $$333, $$332] <- [get-item(string-to-codepoint($$c.getField("c_state")), 0), $$c.getField("c_d_id"), $$c.getField("c_w_id"), $$c.getField("c_id")] project: [$$311, $$333, $$334, $$332] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                    -- ASSIGN  |PARTITIONED|
-                                                                      project ([$$c]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                      -- STREAM_PROJECT  |PARTITIONED|
-                                                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                          data-scan []<-[$$300, $$c] <- test.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                                  -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                                                    select (lt($$296, 1000)) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                    -- STREAM_SELECT  |PARTITIONED|
+                                                                      assign [$$296, $$295] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$296, $$295] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                      -- ASSIGN  |PARTITIONED|
+                                                                        project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                        -- STREAM_PROJECT  |PARTITIONED|
+                                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                            data-scan []<-[$$297, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                                            -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
                                                           exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                          -- HASH_PARTITION_EXCHANGE [$$324]  |PARTITIONED|
+                                                          -- BROADCAST_EXCHANGE  |PARTITIONED|
                                                             select (and(lt($$324, 1000), like($$i.getField("i_data"), "%b"))) project: [$$324] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- STREAM_SELECT  |PARTITIONED|
                                                               assign [$$324] <- [$$i.getField("i_id")] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q9.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q9.plan
index d078a41..41086fb 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q9.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/ch2/ch2_q9.plan
@@ -1,136 +1,136 @@
-distribute result [$$196] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+distribute result [$$196] [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+  exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$196] <- [{"n_name": $$n_name, "l_year": $#1, "SUM_profit": round($$212, 2)}] project: [$$196] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+    assign [$$196] <- [{"n_name": $$n_name, "l_year": $#1, "SUM_profit": round($$212, 2)}] project: [$$196] [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+      exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
       -- SORT_MERGE_EXCHANGE [$$n_name(ASC), $#1(DESC) ]  |PARTITIONED|
         group by ([$$n_name := $$231; $#1 := $$232]) decor ([]) {
-                  aggregate [$$212] <- [agg-global-sql-sum($$230)]
+                  aggregate [$$212] <- [agg-global-sql-sum($$230)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                   -- AGGREGATE  |LOCAL|
-                    nested tuple source
+                    nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-               } [cardinality: 0.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
+               } [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
         -- SORT_GROUP_BY[$$231, $$232]  |PARTITIONED|
-          exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+          exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
           -- HASH_PARTITION_EXCHANGE [$$231, $$232]  |PARTITIONED|
             group by ([$$231 := $$225; $$232 := $$198]) decor ([]) {
-                      aggregate [$$230] <- [agg-local-sql-sum($$218)]
+                      aggregate [$$230] <- [agg-local-sql-sum($$218)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
-                        nested tuple source
+                        nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   } [cardinality: 0.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                   } [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
             -- SORT_GROUP_BY[$$225, $$198]  |PARTITIONED|
-              exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+              exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                assign [$$198] <- [get-year(date($$219))] project: [$$218, $$225, $$198] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                assign [$$198] <- [get-year(date($$219))] project: [$$218, $$225, $$198] [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                 -- ASSIGN  |PARTITIONED|
-                  project ([$$218, $$219, $$225]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                  project ([$$218, $$219, $$225]) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                    exchange [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      join (eq($$213, $$214)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+                      join (eq($$213, $$214)) [cardinality: 9.223372036854776E16, doc-size: -5.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                       -- HYBRID_HASH_JOIN [$$213][$$214]  |PARTITIONED|
-                        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.0002E11]
+                        exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          project ([$$218, $$219, $$213]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.0002E11]
+                          project ([$$218, $$219, $$213]) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                           -- STREAM_PROJECT  |PARTITIONED|
-                            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.0002E11]
+                            exchange [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              join (eq($$229, $$224)) [cardinality: 9.223372036854776E16, op-cost: 5.00004E11, total-cost: 5.0002E11]
+                              join (eq($$229, $$224)) [cardinality: 9.223372036854776E16, doc-size: -4.0, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
                               -- HYBRID_HASH_JOIN [$$229][$$224]  |PARTITIONED|
-                                exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                                exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  assign [$$229] <- [numeric-mod(numeric-multiply($$199, $$200), 10000)] project: [$$218, $$219, $$229] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                                  assign [$$229] <- [numeric-mod(numeric-multiply($$199, $$200), 10000)] project: [$$218, $$219, $$229] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
                                   -- ASSIGN  |PARTITIONED|
-                                    project ([$$218, $$219, $$199, $$200]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                                    project ([$$218, $$219, $$199, $$200]) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
                                     -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                                      exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        join (eq($$206, $$207)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 1.1E7]
+                                        join (eq($$206, $$207)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 2.50004E11, total-cost: 2.50015E11]
                                         -- HYBRID_HASH_JOIN [$$206][$$207]  |PARTITIONED|
-                                          exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-                                          -- HASH_PARTITION_EXCHANGE [$$206]  |PARTITIONED|
-                                            project ([$$218, $$219, $$199, $$200, $$206]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                                            -- STREAM_PROJECT  |PARTITIONED|
-                                              exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                join (and(eq($$206, $$200), eq($$217, $$199))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                                -- HYBRID_HASH_JOIN [$$200, $$199][$$206, $$217]  |PARTITIONED|
-                                                  exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                                  -- HASH_PARTITION_EXCHANGE [$$200, $$199]  |PARTITIONED|
-                                                    assign [$$200, $$199] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$199, $$200] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                    -- ASSIGN  |PARTITIONED|
-                                                      project ([$$s]) [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 []<-[$$201, $$s] <- test.stock [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                                            exchange
-                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              empty-tuple-source
-                                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                  exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                                  -- HASH_PARTITION_EXCHANGE [$$206, $$217]  |PARTITIONED|
-                                                    assign [$$218, $$217, $$206] <- [$$ol.getField("ol_amount"), $$ol.getField("ol_supply_w_id"), $$ol.getField("ol_i_id")] project: [$$218, $$219, $$206, $$217] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                    -- ASSIGN  |PARTITIONED|
-                                                      unnest $$ol <- scan-collection($$215) project: [$$219, $$ol] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                      -- UNNEST  |PARTITIONED|
-                                                        assign [$$219, $$215] <- [$$o.getField("o_entry_d"), $$o.getField("o_orderline")] project: [$$219, $$215] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                        -- ASSIGN  |PARTITIONED|
-                                                          project ([$$o]) [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 []<-[$$202, $$o] <- test.orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                              -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                exchange
-                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  empty-tuple-source
-                                                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                          exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                          -- HASH_PARTITION_EXCHANGE [$$207]  |PARTITIONED|
-                                            select (like($$i.getField("i_data"), "%bb")) project: [$$207] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                            -- STREAM_SELECT  |PARTITIONED|
-                                              assign [$$207] <- [$$i.getField("i_id")] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                              -- ASSIGN  |PARTITIONED|
-                                                project ([$$i]) [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 []<-[$$203, $$i] <- test.item [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                                      exchange
-                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        empty-tuple-source
-                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                  assign [$$224, $$213] <- [$$su.getField("su_suppkey"), $$su.getField("su_nationkey")] project: [$$213, $$224] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                  -- ASSIGN  |PARTITIONED|
-                                    project ([$$su]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                    -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        data-scan []<-[$$204, $$su] <- test.supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                        -- DATASOURCE_SCAN  |PARTITIONED|
-                                          exchange
+                                          exchange [cardinality: 2.5E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            empty-tuple-source
+                                            project ([$$218, $$219, $$199, $$200, $$206]) [cardinality: 2.5E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                            -- STREAM_PROJECT  |PARTITIONED|
+                                              exchange [cardinality: 2.5E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                join (and(eq($$206, $$200), eq($$217, $$199))) [cardinality: 2.5E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                -- HYBRID_HASH_JOIN [$$200, $$199][$$206, $$217]  |PARTITIONED|
+                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  -- HASH_PARTITION_EXCHANGE [$$200, $$199]  |PARTITIONED|
+                                                    assign [$$200, $$199] <- [$$s.getField("s_i_id"), $$s.getField("s_w_id")] project: [$$199, $$200] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- ASSIGN  |PARTITIONED|
+                                                      project ([$$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      -- STREAM_PROJECT  |PARTITIONED|
+                                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                          data-scan []<-[$$201, $$s] <- test.stock [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                          -- DATASOURCE_SCAN  |PARTITIONED|
+                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  -- HASH_PARTITION_EXCHANGE [$$206, $$217]  |PARTITIONED|
+                                                    assign [$$218, $$217, $$206] <- [$$ol.getField("ol_amount"), $$ol.getField("ol_supply_w_id"), $$ol.getField("ol_i_id")] project: [$$218, $$219, $$206, $$217] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- ASSIGN  |PARTITIONED|
+                                                      unnest $$ol <- scan-collection($$215) project: [$$219, $$ol] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      -- UNNEST  |PARTITIONED|
+                                                        assign [$$219, $$215] <- [$$o.getField("o_entry_d"), $$o.getField("o_orderline")] project: [$$219, $$215] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        -- ASSIGN  |PARTITIONED|
+                                                          project ([$$o]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                          -- STREAM_PROJECT  |PARTITIONED|
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                              data-scan []<-[$$202, $$o] <- test.orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                              -- DATASOURCE_SCAN  |PARTITIONED|
+                                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                            select (like($$i.getField("i_data"), "%bb")) project: [$$207] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                            -- STREAM_SELECT  |PARTITIONED|
+                                              assign [$$207] <- [$$i.getField("i_id")] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- ASSIGN  |PARTITIONED|
+                                                project ([$$i]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- STREAM_PROJECT  |PARTITIONED|
+                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                    data-scan []<-[$$203, $$i] <- test.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- DATASOURCE_SCAN  |PARTITIONED|
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                  assign [$$224, $$213] <- [$$su.getField("su_suppkey"), $$su.getField("su_nationkey")] project: [$$213, $$224] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                  -- ASSIGN  |PARTITIONED|
+                                    project ([$$su]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    -- STREAM_PROJECT  |PARTITIONED|
+                                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        data-scan []<-[$$204, $$su] <- test.supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                        -- DATASOURCE_SCAN  |PARTITIONED|
+                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                         -- BROADCAST_EXCHANGE  |PARTITIONED|
-                          assign [$$225, $$214] <- [$$n.getField("n_name"), $$n.getField("n_nationkey")] project: [$$225, $$214] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                          assign [$$225, $$214] <- [$$n.getField("n_name"), $$n.getField("n_nationkey")] project: [$$225, $$214] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                           -- ASSIGN  |PARTITIONED|
-                            project ([$$n]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                            project ([$$n]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                             -- STREAM_PROJECT  |PARTITIONED|
-                              exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                data-scan []<-[$$205, $$n] <- test.nation [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                data-scan []<-[$$205, $$n] <- test.nation [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                 -- DATASOURCE_SCAN  |PARTITIONED|
-                                  exchange
+                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    empty-tuple-source
+                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- 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.3.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.3.plan
index 622dfac..661b55d 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.3.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/hash-join-with-redundant-variable/hash-join-with-redundant-variable.3.plan
@@ -1,68 +1,68 @@
-distribute result [$$76] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+distribute result [$$76] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+  exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    aggregate [$$76] <- [agg-sql-sum($$77)] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+    aggregate [$$76] <- [agg-sql-sum($$77)] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
     -- AGGREGATE  |UNPARTITIONED|
-      exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+      exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
       -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-        aggregate [$$77] <- [agg-sql-count(1)] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+        aggregate [$$77] <- [agg-sql-count(1)] [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
         -- AGGREGATE  |PARTITIONED|
-          exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+          exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 2.50015E11]
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            join (eq($$70, $$72)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 1.1E7]
+            join (eq($$70, $$72)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 2.50004E11, total-cost: 2.50015E11]
             -- HYBRID_HASH_JOIN [$$70][$$72]  |PARTITIONED|
-              exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-              -- HASH_PARTITION_EXCHANGE [$$70]  |PARTITIONED|
-                project ([$$70]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
+              exchange [cardinality: 2.5E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                project ([$$70]) [cardinality: 2.5E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                 -- STREAM_PROJECT  |PARTITIONED|
-                  exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
+                  exchange [cardinality: 2.5E11, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    join (and(eq($$71, $$70), eq($$78, $$79))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                    join (and(eq($$71, $$70), eq($$78, $$79))) [cardinality: 2.5E11, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
                     -- HYBRID_HASH_JOIN [$$71, $$79][$$70, $$78]  |PARTITIONED|
-                      exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        assign [$$79] <- [$$71] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                        assign [$$79] <- [$$71] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                         -- ASSIGN  |PARTITIONED|
-                          assign [$$71] <- [$$r.getField("x")] project: [$$71] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                          assign [$$71] <- [$$r.getField("x")] project: [$$71] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                           -- ASSIGN  |PARTITIONED|
-                            project ([$$r]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                            project ([$$r]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                             -- STREAM_PROJECT  |PARTITIONED|
-                              exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                data-scan []<-[$$73, $$r] <- test.region [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                data-scan []<-[$$73, $$r] <- test.region [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                 -- DATASOURCE_SCAN  |PARTITIONED|
-                                  exchange
+                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    empty-tuple-source
+                                    empty-tuple-source [cardinality: 0.0, doc-size: 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]
+                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        assign [$$78] <- [$$70] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                        assign [$$78] <- [$$70] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                         -- ASSIGN  |PARTITIONED|
-                          assign [$$70] <- [$$o.getField("x")] project: [$$70] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                          assign [$$70] <- [$$o.getField("x")] project: [$$70] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                           -- ASSIGN  |PARTITIONED|
-                            project ([$$o]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                            project ([$$o]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                             -- STREAM_PROJECT  |PARTITIONED|
-                              exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                data-scan []<-[$$75, $$o] <- test.orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                data-scan []<-[$$75, $$o] <- test.orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                 -- DATASOURCE_SCAN  |PARTITIONED|
-                                  exchange
+                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    empty-tuple-source
+                                    empty-tuple-source [cardinality: 0.0, doc-size: 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 [$$72]  |PARTITIONED|
-                assign [$$72] <- [$$n.getField("x")] project: [$$72] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+              -- BROADCAST_EXCHANGE  |PARTITIONED|
+                assign [$$72] <- [$$n.getField("x")] project: [$$72] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                 -- ASSIGN  |PARTITIONED|
-                  project ([$$n]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                  project ([$$n]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      data-scan []<-[$$74, $$n] <- test.nation [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                      data-scan []<-[$$74, $$n] <- test.nation [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                       -- DATASOURCE_SCAN  |PARTITIONED|
-                        exchange
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          empty-tuple-source
+                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/nlj_partitioning_property_1.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/nlj_partitioning_property_1.plan
index 59ba862..722599c 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/nlj_partitioning_property_1.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/nlj_partitioning_property_1.plan
@@ -1,56 +1,60 @@
-distribute result [$$75] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+distribute result [$$75] [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+  exchange [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    assign [$$75] <- [{"count": $$82}] project: [$$75] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+    assign [$$75] <- [{"count": $$82}] project: [$$75] [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
     -- ASSIGN  |UNPARTITIONED|
-      aggregate [$$82] <- [agg-sql-sum($$84)] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+      aggregate [$$82] <- [agg-sql-sum($$84)] [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
       -- AGGREGATE  |UNPARTITIONED|
-        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+        exchange [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
         -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-          aggregate [$$84] <- [agg-sql-count(1)] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+          aggregate [$$84] <- [agg-sql-count(1)] [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
           -- AGGREGATE  |PARTITIONED|
-            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 2.000015E12]
+            exchange [cardinality: 1.0E12, doc-size: -3.0, op-cost: 0.0, total-cost: 1.000016E12]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              join (eq($$76, $$78)) [cardinality: 9.223372036854776E16, op-cost: 1.000004E12, total-cost: 2.000015E12]
-              -- HYBRID_HASH_JOIN [$$76][$$78]  |PARTITIONED|
-                exchange [cardinality: 1.0E12, op-cost: 0.0, total-cost: 1.000006E12]
+              join (true) [cardinality: 1.0E12, doc-size: -3.0, op-cost: 1.0E12, total-cost: 1.000016E12]
+              -- NESTED_LOOP  |PARTITIONED|
+                exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 1.1E7]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  join (true) [cardinality: 1.0E12, op-cost: 1.0E12, total-cost: 1.000006E12]
-                  -- NESTED_LOOP  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      project ([$$76]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          data-scan []<-[$$76, $$s] <- tpch.Supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                          -- DATASOURCE_SCAN  |PARTITIONED|
-                            exchange
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              empty-tuple-source
-                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                      project ([]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          data-scan []<-[$$79, $$p] <- tpch.Part [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                          -- DATASOURCE_SCAN  |PARTITIONED|
-                            exchange
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              empty-tuple-source
-                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                -- BROADCAST_EXCHANGE  |PARTITIONED|
-                  project ([$$78]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                  project ([]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 1.1E7]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                    exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 1.1E7]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      data-scan []<-[$$77, $$78, $$ps] <- tpch.Partsupp [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                      -- DATASOURCE_SCAN  |PARTITIONED|
-                        exchange
+                      join (eq($$76, $$78)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 5000000.0, total-cost: 1.1E7]
+                      -- HYBRID_HASH_JOIN [$$76][$$78]  |PARTITIONED|
+                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          empty-tuple-source
+                          project ([$$76]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                          -- STREAM_PROJECT  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              data-scan []<-[$$76, $$s] <- tpch.Supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- DATASOURCE_SCAN  |PARTITIONED|
+                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                        -- BROADCAST_EXCHANGE  |PARTITIONED|
+                          project ([$$78]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                          -- STREAM_PROJECT  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              data-scan []<-[$$77, $$78, $$ps] <- tpch.Partsupp [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- DATASOURCE_SCAN  |PARTITIONED|
+                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                -- BROADCAST_EXCHANGE  |PARTITIONED|
+                  project ([]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                  -- STREAM_PROJECT  |PARTITIONED|
+                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      data-scan []<-[$$79, $$p] <- tpch.Part [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                      -- DATASOURCE_SCAN  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q08_group_by.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q08_group_by.plan
index 16de373..504fb0f 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q08_group_by.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q08_group_by.plan
@@ -1,140 +1,140 @@
-distribute result [$$203] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+distribute result [$$203] [cardinality: 1000000.0, doc-size: -7.0, op-cost: 0.0, total-cost: 3.1E7]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+  exchange [cardinality: 1000000.0, doc-size: -7.0, op-cost: 0.0, total-cost: 3.1E7]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$203] <- [{"o_orderdate": $$228, "l_discount": $$231, "l_extendedprice": $$232, "l_suppkey": $$233, "s_nationkey": $$242}] project: [$$203] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+    assign [$$203] <- [{"o_orderdate": $$228, "l_discount": $$231, "l_extendedprice": $$232, "l_suppkey": $$233, "s_nationkey": $$242}] project: [$$203] [cardinality: 1000000.0, doc-size: -7.0, op-cost: 0.0, total-cost: 3.1E7]
     -- ASSIGN  |PARTITIONED|
-      project ([$$228, $$231, $$232, $$233, $$242]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+      project ([$$228, $$231, $$232, $$233, $$242]) [cardinality: 1000000.0, doc-size: -7.0, op-cost: 0.0, total-cost: 3.1E7]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+        exchange [cardinality: 1000000.0, doc-size: -7.0, op-cost: 0.0, total-cost: 3.1E7]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-          join (eq($$212, $$230)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+          join (eq($$212, $$230)) [cardinality: 1000000.0, doc-size: -7.0, op-cost: 2000000.0, total-cost: 3.1E7]
           -- HYBRID_HASH_JOIN [$$230][$$212]  |PARTITIONED|
-            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
-            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              project ([$$228, $$231, $$232, $$233, $$242, $$230]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+            exchange [cardinality: 1000000.0, doc-size: -6.0, op-cost: 0.0, total-cost: 2.6E7]
+            -- HASH_PARTITION_EXCHANGE [$$230]  |PARTITIONED|
+              project ([$$228, $$231, $$232, $$233, $$242, $$230]) [cardinality: 1000000.0, doc-size: -6.0, op-cost: 0.0, total-cost: 2.6E7]
               -- STREAM_PROJECT  |PARTITIONED|
-                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                exchange [cardinality: 1000000.0, doc-size: -6.0, op-cost: 0.0, total-cost: 2.6E7]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  join (eq($$216, $$211)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+                  join (eq($$216, $$211)) [cardinality: 1000000.0, doc-size: -6.0, op-cost: 2000000.0, total-cost: 2.6E7]
                   -- HYBRID_HASH_JOIN [$$216][$$211]  |PARTITIONED|
-                    exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
-                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      project ([$$228, $$231, $$232, $$233, $$242, $$230, $$216]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                    exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
+                    -- HASH_PARTITION_EXCHANGE [$$216]  |PARTITIONED|
+                      project ([$$228, $$231, $$232, $$233, $$242, $$230, $$216]) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                       -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                        exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          join (eq($$218, $$210)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+                          join (eq($$218, $$210)) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 2000000.0, total-cost: 2.1E7]
                           -- HYBRID_HASH_JOIN [$$218][$$210]  |PARTITIONED|
-                            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              project ([$$228, $$231, $$232, $$233, $$242, $$230, $$218]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                            exchange [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                            -- HASH_PARTITION_EXCHANGE [$$218]  |PARTITIONED|
+                              project ([$$228, $$231, $$232, $$233, $$242, $$230, $$218]) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
                               -- STREAM_PROJECT  |PARTITIONED|
-                                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                                exchange [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  join (eq($$209, $$221)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+                                  join (eq($$209, $$221)) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 2000000.0, total-cost: 1.6E7]
                                   -- HYBRID_HASH_JOIN [$$221][$$209]  |PARTITIONED|
-                                    exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.00015E11]
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      project ([$$228, $$231, $$232, $$233, $$242, $$230, $$221]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.00015E11]
+                                    exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                    -- HASH_PARTITION_EXCHANGE [$$221]  |PARTITIONED|
+                                      project ([$$228, $$231, $$232, $$233, $$242, $$230, $$221]) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
                                       -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.00015E11]
+                                        exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          join (eq($$206, $$208)) [cardinality: 9.223372036854776E16, op-cost: 5.00004E11, total-cost: 5.00015E11]
+                                          join (eq($$206, $$208)) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
                                           -- HYBRID_HASH_JOIN [$$206][$$208]  |PARTITIONED|
-                                            exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 6000000.0]
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              project ([$$231, $$232, $$233, $$242, $$230, $$206]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 6000000.0]
+                                            exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                            -- HASH_PARTITION_EXCHANGE [$$206]  |PARTITIONED|
+                                              project ([$$231, $$232, $$233, $$242, $$230, $$206]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 6000000.0]
+                                                exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (eq($$205, $$233)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                  join (eq($$205, $$233)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
                                                   -- HYBRID_HASH_JOIN [$$205][$$233]  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      assign [$$242] <- [$$s.getField(3)] project: [$$242, $$205] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      assign [$$242] <- [$$s.getField(3)] project: [$$242, $$205] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- ASSIGN  |PARTITIONED|
-                                                        exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          data-scan []<-[$$205, $$s] <- q08_group_by.Supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                          data-scan []<-[$$205, $$s] <- q08_group_by.Supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- DATASOURCE_SCAN  |PARTITIONED|
-                                                            exchange
+                                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              empty-tuple-source
+                                                              empty-tuple-source [cardinality: 0.0, doc-size: 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]
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                     -- HASH_PARTITION_EXCHANGE [$$233]  |PARTITIONED|
-                                                      assign [$$233, $$232, $$231, $$230] <- [$$l.getField(2), $$l.getField(5), $$l.getField(6), $$l.getField(1)] project: [$$231, $$232, $$233, $$230, $$206] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                      assign [$$233, $$232, $$231, $$230] <- [$$l.getField(2), $$l.getField(5), $$l.getField(6), $$l.getField(1)] project: [$$231, $$232, $$233, $$230, $$206] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- ASSIGN  |PARTITIONED|
-                                                        project ([$$206, $$l]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        project ([$$206, $$l]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- STREAM_PROJECT  |PARTITIONED|
-                                                          exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$206, $$207, $$l] <- q08_group_by.LineItem [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                            data-scan []<-[$$206, $$207, $$l] <- q08_group_by.LineItem [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
-                                                              exchange
+                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                empty-tuple-source
+                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                            exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                            -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                              select (and(ge($$228, "1995-01-01"), le($$228, "1996-12-31"))) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                              -- STREAM_SELECT  |PARTITIONED|
-                                                assign [$$228, $$221] <- [$$o.getField(4), $$o.getField(1)] project: [$$208, $$228, $$221] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                                -- ASSIGN  |PARTITIONED|
-                                                  exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    data-scan []<-[$$208, $$o] <- q08_group_by.Orders [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                                      exchange
-                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        empty-tuple-source
-                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                      assign [$$218] <- [$$c.getField(3)] project: [$$218, $$209] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                      -- ASSIGN  |PARTITIONED|
-                                        exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          data-scan []<-[$$209, $$c] <- q08_group_by.Customer [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                            exchange
+                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              empty-tuple-source
-                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                            -- BROADCAST_EXCHANGE  |PARTITIONED|
-                              assign [$$216] <- [$$n1.getField(2)] project: [$$216, $$210] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                              -- ASSIGN  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  data-scan []<-[$$210, $$n1] <- q08_group_by.Nation [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                  -- DATASOURCE_SCAN  |PARTITIONED|
-                                    exchange
+                                              select (and(ge($$228, "1995-01-01"), le($$228, "1996-12-31"))) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- STREAM_SELECT  |PARTITIONED|
+                                                assign [$$228, $$221] <- [$$o.getField(4), $$o.getField(1)] project: [$$208, $$228, $$221] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- ASSIGN  |PARTITIONED|
+                                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                    data-scan []<-[$$208, $$o] <- q08_group_by.Orders [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- DATASOURCE_SCAN  |PARTITIONED|
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      empty-tuple-source
-                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                      select (eq($$r1.getField(1), "AMERICA")) project: [$$211] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                      -- STREAM_SELECT  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          data-scan []<-[$$211, $$r1] <- q08_group_by.Region [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                          -- DATASOURCE_SCAN  |PARTITIONED|
-                            exchange
+                                      assign [$$218] <- [$$c.getField(3)] project: [$$218, $$209] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                      -- ASSIGN  |PARTITIONED|
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          data-scan []<-[$$209, $$c] <- q08_group_by.Customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- DATASOURCE_SCAN  |PARTITIONED|
+                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              empty-tuple-source
-                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-            exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-            -- BROADCAST_EXCHANGE  |PARTITIONED|
-              select (eq($$p.getField(4), "ECONOMY ANODIZED STEEL")) project: [$$212] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-              -- STREAM_SELECT  |PARTITIONED|
-                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  data-scan []<-[$$212, $$p] <- q08_group_by.Part [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                  -- DATASOURCE_SCAN  |PARTITIONED|
-                    exchange
+                              assign [$$216] <- [$$n1.getField(2)] project: [$$216, $$210] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- ASSIGN  |PARTITIONED|
+                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  data-scan []<-[$$210, $$n1] <- q08_group_by.Nation [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                  -- DATASOURCE_SCAN  |PARTITIONED|
+                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      empty-tuple-source
+                      select (eq($$r1.getField(1), "AMERICA")) project: [$$211] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                      -- STREAM_SELECT  |PARTITIONED|
+                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          data-scan []<-[$$211, $$r1] <- q08_group_by.Region [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                          -- DATASOURCE_SCAN  |PARTITIONED|
+                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+              select (eq($$p.getField(4), "ECONOMY ANODIZED STEEL")) project: [$$212] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+              -- STREAM_SELECT  |PARTITIONED|
+                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                  data-scan []<-[$$212, $$p] <- q08_group_by.Part [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                  -- DATASOURCE_SCAN  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q09_group_by.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q09_group_by.plan
index 90ca371..2da49a9 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q09_group_by.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/q09_group_by.plan
@@ -1,98 +1,92 @@
-distribute result [$$145] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+distribute result [$$145] [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+  exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$145] <- [{"l_extendedprice": $$166, "l_discount": $$167, "l_quantity": $$168, "l_orderkey": $$152, "n_name": $$165, "ps_supplycost": $$177}] project: [$$145] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+    assign [$$145] <- [{"l_extendedprice": $$166, "l_discount": $$167, "l_quantity": $$168, "l_orderkey": $$152, "n_name": $$165, "ps_supplycost": $$177}] project: [$$145] [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
     -- ASSIGN  |PARTITIONED|
-      project ([$$166, $$167, $$168, $$152, $$177, $$165]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+      project ([$$165, $$177, $$166, $$167, $$168, $$152]) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+        exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-          join (eq($$151, $$157)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
-          -- HYBRID_HASH_JOIN [$$157][$$151]  |PARTITIONED|
-            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.0002E11]
-            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              project ([$$166, $$167, $$168, $$152, $$177, $$157]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.0002E11]
+          join (and(eq($$147, $$169), eq($$149, $$154))) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 2000000.0, total-cost: 2.1E7]
+          -- HYBRID_HASH_JOIN [$$147, $$149][$$169, $$154]  |PARTITIONED|
+            exchange [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+            -- HASH_PARTITION_EXCHANGE [$$147, $$149]  |PARTITIONED|
+              project ([$$165, $$177, $$147, $$149]) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
               -- STREAM_PROJECT  |PARTITIONED|
-                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.0002E11]
-                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  join (eq($$150, $$154)) [cardinality: 9.223372036854776E16, op-cost: 5.00004E11, total-cost: 5.0002E11]
-                  -- HYBRID_HASH_JOIN [$$154][$$150]  |PARTITIONED|
-                    exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
-                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      project ([$$166, $$167, $$168, $$152, $$177, $$154]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
-                      -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          join (eq($$147, $$169)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 1.1E7]
-                          -- HYBRID_HASH_JOIN [$$169][$$147]  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-                            -- HASH_PARTITION_EXCHANGE [$$169]  |PARTITIONED|
-                              project ([$$166, $$167, $$168, $$152, $$177, $$154, $$169]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 6000000.0]
-                              -- STREAM_PROJECT  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 7000000.0]
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  join (and(eq($$148, $$169), eq($$149, $$154))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                  -- HYBRID_HASH_JOIN [$$148, $$149][$$169, $$154]  |PARTITIONED|
-                                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      assign [$$177] <- [$$ps.getField(3)] project: [$$177, $$148, $$149] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                      -- ASSIGN  |PARTITIONED|
-                                        exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          data-scan []<-[$$148, $$149, $$ps] <- q09_group_by.Partsupp [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                            exchange
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              empty-tuple-source
-                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                    -- HASH_PARTITION_EXCHANGE [$$169, $$154]  |PARTITIONED|
-                                      assign [$$169, $$168, $$167, $$166, $$154] <- [$$l.getField(1), $$l.getField(4), $$l.getField(6), $$l.getField(5), $$l.getField(2)] project: [$$166, $$167, $$168, $$152, $$154, $$169] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                      -- ASSIGN  |PARTITIONED|
-                                        project ([$$152, $$l]) [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 []<-[$$152, $$153, $$l] <- q09_group_by.LineItem [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                            -- DATASOURCE_SCAN  |PARTITIONED|
-                                              exchange
-                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                empty-tuple-source
-                                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              select (contains($$p.getField(1), "green")) project: [$$147] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                              -- STREAM_SELECT  |PARTITIONED|
-                                exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  data-scan []<-[$$147, $$p] <- q09_group_by.Part [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                  -- DATASOURCE_SCAN  |PARTITIONED|
-                                    exchange
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      empty-tuple-source
-                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                      assign [$$157] <- [$$s.getField(3)] project: [$$157, $$150] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                      -- ASSIGN  |PARTITIONED|
-                        exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          data-scan []<-[$$150, $$s] <- q09_group_by.Supplier [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                          -- DATASOURCE_SCAN  |PARTITIONED|
-                            exchange
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              empty-tuple-source
-                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-            exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-            -- BROADCAST_EXCHANGE  |PARTITIONED|
-              assign [$$165] <- [$$n.getField(1)] project: [$$165, $$151] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                project ([$$165, $$177, $$147, $$148, $$149, $$150]) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                -- STREAM_PROJECT  |PARTITIONED|
+                  exchange [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                    join (eq($$151, $$157)) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 2000000.0, total-cost: 1.6E7]
+                    -- HYBRID_HASH_JOIN [$$157][$$151]  |PARTITIONED|
+                      exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                      -- HASH_PARTITION_EXCHANGE [$$157]  |PARTITIONED|
+                        join (eq($$149, $$150)) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
+                        -- HYBRID_HASH_JOIN [$$149][$$150]  |PARTITIONED|
+                          exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                          -- HASH_PARTITION_EXCHANGE [$$149]  |PARTITIONED|
+                            join (eq($$147, $$148)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                            -- HYBRID_HASH_JOIN [$$147][$$148]  |PARTITIONED|
+                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                select (contains($$p.getField(1), "green")) project: [$$147] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                -- STREAM_SELECT  |PARTITIONED|
+                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    data-scan []<-[$$147, $$p] <- q09_group_by.Part [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    -- DATASOURCE_SCAN  |PARTITIONED|
+                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- HASH_PARTITION_EXCHANGE [$$148]  |PARTITIONED|
+                                assign [$$177] <- [$$ps.getField(3)] project: [$$177, $$148, $$149] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                -- ASSIGN  |PARTITIONED|
+                                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    data-scan []<-[$$148, $$149, $$ps] <- q09_group_by.Partsupp [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    -- DATASOURCE_SCAN  |PARTITIONED|
+                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            assign [$$157] <- [$$s.getField(3)] project: [$$150, $$157] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                            -- ASSIGN  |PARTITIONED|
+                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                data-scan []<-[$$150, $$s] <- q09_group_by.Supplier [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                -- DATASOURCE_SCAN  |PARTITIONED|
+                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                      exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        assign [$$165] <- [$$n.getField(1)] project: [$$165, $$151] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                        -- ASSIGN  |PARTITIONED|
+                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                            data-scan []<-[$$151, $$n] <- q09_group_by.Nation [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                            -- DATASOURCE_SCAN  |PARTITIONED|
+                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+            -- HASH_PARTITION_EXCHANGE [$$169, $$154]  |PARTITIONED|
+              assign [$$169, $$168, $$167, $$166, $$154] <- [$$l.getField(1), $$l.getField(4), $$l.getField(6), $$l.getField(5), $$l.getField(2)] project: [$$166, $$167, $$168, $$152, $$169, $$154] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
               -- ASSIGN  |PARTITIONED|
-                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  data-scan []<-[$$151, $$n] <- q09_group_by.Nation [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                  -- DATASOURCE_SCAN  |PARTITIONED|
-                    exchange
-                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      empty-tuple-source
-                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                project ([$$152, $$l]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                -- STREAM_PROJECT  |PARTITIONED|
+                  exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                    data-scan []<-[$$152, $$153, $$l] <- q09_group_by.LineItem [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                    -- DATASOURCE_SCAN  |PARTITIONED|
+                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1580.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1580.plan
index f5eba1e..209ca40 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1580.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1580.plan
@@ -1,132 +1,132 @@
-distribute result [$$125] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+distribute result [$$125] [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+  exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    limit 100 [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+    limit 100 [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
     -- STREAM_LIMIT  |UNPARTITIONED|
-      assign [$$125] <- [{"state": $$ca_state, "cnt": $$136}] project: [$$125] [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+      assign [$$125] <- [{"state": $$ca_state, "cnt": $$136}] project: [$$125] [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
       -- ASSIGN  |PARTITIONED|
-        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+        exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
         -- SORT_MERGE_EXCHANGE [$$136(ASC) ]  |PARTITIONED|
-          limit 100 [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+          limit 100 [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
           -- STREAM_LIMIT  |PARTITIONED|
-            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+            exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              order (topK: 100) (ASC, $$136) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+              order (topK: 100) (ASC, $$136) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
               -- STABLE_SORT [topK: 100] [$$136(ASC)]  |PARTITIONED|
-                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  select (ge($$135, 10)) project: [$$ca_state, $$136]
+                  select (ge($$135, 10)) project: [$$ca_state, $$136] [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                   -- STREAM_SELECT  |PARTITIONED|
-                    exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                    exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                       group by ([$$ca_state := $$145]) decor ([]) {
-                                aggregate [$$135, $$136] <- [agg-sql-sum($$143), agg-sql-sum($$144)]
+                                aggregate [$$135, $$136] <- [agg-sql-sum($$143), agg-sql-sum($$144)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- AGGREGATE  |LOCAL|
-                                  nested tuple source
+                                  nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
-                             } [cardinality: 0.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                             } [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                       -- SORT_GROUP_BY[$$145]  |PARTITIONED|
-                        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                        exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                         -- HASH_PARTITION_EXCHANGE [$$145]  |PARTITIONED|
                           group by ([$$145 := $$126]) decor ([]) {
-                                    aggregate [$$143, $$144] <- [agg-sql-count($$a), agg-sql-count($$a)]
+                                    aggregate [$$143, $$144] <- [agg-sql-count($$a), agg-sql-count($$a)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- AGGREGATE  |LOCAL|
-                                      nested tuple source
+                                      nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                 } [cardinality: 0.0, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                                 } [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                           -- SORT_GROUP_BY[$$126]  |PARTITIONED|
-                            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                            exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              project ([$$a, $$126]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                              project ([$$a, $$126]) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                               -- STREAM_PROJECT  |PARTITIONED|
-                                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                                exchange [cardinality: 1000000.0, doc-size: -5.0, op-cost: 0.0, total-cost: 2.1E7]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  join (eq($$129, $$132)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+                                  join (eq($$129, $$132)) [cardinality: 1000000.0, doc-size: -5.0, op-cost: 2000000.0, total-cost: 2.1E7]
                                   -- HYBRID_HASH_JOIN [$$129][$$132]  |PARTITIONED|
-                                    exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      project ([$$a, $$126, $$129]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                                    exchange [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
+                                    -- HASH_PARTITION_EXCHANGE [$$129]  |PARTITIONED|
+                                      project ([$$a, $$126, $$129]) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
                                       -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 9.223372036854776E16]
+                                        exchange [cardinality: 1000000.0, doc-size: -4.0, op-cost: 0.0, total-cost: 1.6E7]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          join (eq($$137, $$131)) [cardinality: 9.223372036854776E16, op-cost: 9.223372036854776E16, total-cost: 9.223372036854776E16]
+                                          join (eq($$137, $$131)) [cardinality: 1000000.0, doc-size: -4.0, op-cost: 2000000.0, total-cost: 1.6E7]
                                           -- HYBRID_HASH_JOIN [$$137][$$131]  |PARTITIONED|
-                                            exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.00015E11]
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              project ([$$a, $$126, $$129, $$137]) [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.00015E11]
+                                            exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
+                                            -- HASH_PARTITION_EXCHANGE [$$137]  |PARTITIONED|
+                                              project ([$$a, $$126, $$129, $$137]) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
                                               -- STREAM_PROJECT  |PARTITIONED|
-                                                exchange [cardinality: 9.223372036854776E16, op-cost: 0.0, total-cost: 5.00015E11]
+                                                exchange [cardinality: 1000000.0, doc-size: -3.0, op-cost: 0.0, total-cost: 1.1E7]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (eq($$128, $$142)) [cardinality: 9.223372036854776E16, op-cost: 5.00004E11, total-cost: 5.00015E11]
+                                                  join (eq($$128, $$142)) [cardinality: 1000000.0, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
                                                   -- HYBRID_HASH_JOIN [$$128][$$142]  |PARTITIONED|
-                                                    exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 6000000.0]
-                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      project ([$$a, $$126, $$128]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 6000000.0]
+                                                    exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                                    -- HASH_PARTITION_EXCHANGE [$$128]  |PARTITIONED|
+                                                      project ([$$a, $$126, $$128]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                       -- STREAM_PROJECT  |PARTITIONED|
-                                                        exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 6000000.0]
+                                                        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          join (eq($$127, $$140)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 6000000.0]
+                                                          join (eq($$127, $$140)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
                                                           -- HYBRID_HASH_JOIN [$$127][$$140]  |PARTITIONED|
-                                                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                              assign [$$126] <- [$$a.getField(8)] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                              assign [$$126] <- [$$a.getField(8)] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                               -- ASSIGN  |PARTITIONED|
-                                                                exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  data-scan []<-[$$127, $$a] <- tpcds.customer_address [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                                  data-scan []<-[$$127, $$a] <- tpcds.customer_address [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                   -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                    exchange
+                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      empty-tuple-source
+                                                                      empty-tuple-source [cardinality: 0.0, doc-size: 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]
+                                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- HASH_PARTITION_EXCHANGE [$$140]  |PARTITIONED|
-                                                              assign [$$140] <- [$$c.getField(4)] project: [$$128, $$140] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                              assign [$$140] <- [$$c.getField(4)] project: [$$128, $$140] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                               -- ASSIGN  |PARTITIONED|
-                                                                exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                  data-scan []<-[$$128, $$c] <- tpcds.customer [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                                  data-scan []<-[$$128, $$c] <- tpcds.customer [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                                   -- DATASOURCE_SCAN  |PARTITIONED|
-                                                                    exchange
+                                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                      empty-tuple-source
+                                                                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                                      assign [$$137, $$142] <- [$$s.getField(0), $$s.getField(3)] project: [$$129, $$137, $$142] [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                    -- HASH_PARTITION_EXCHANGE [$$142]  |PARTITIONED|
+                                                      assign [$$137, $$142] <- [$$s.getField(0), $$s.getField(3)] project: [$$129, $$137, $$142] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                       -- ASSIGN  |PARTITIONED|
-                                                        project ([$$129, $$s]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                        project ([$$129, $$s]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                         -- STREAM_PROJECT  |PARTITIONED|
-                                                          exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
+                                                          exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                            data-scan []<-[$$129, $$130, $$s] <- tpcds.store_sales [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                                            data-scan []<-[$$129, $$130, $$s] <- tpcds.store_sales [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                                             -- DATASOURCE_SCAN  |PARTITIONED|
-                                                              exchange
+                                                              exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                empty-tuple-source
+                                                                empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                            exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                            -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                              project ([$$131]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                              -- STREAM_PROJECT  |PARTITIONED|
-                                                exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  data-scan []<-[$$131, $$d] <- tpcds.date_dim [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                  -- DATASOURCE_SCAN  |PARTITIONED|
-                                                    exchange
-                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      empty-tuple-source
-                                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                    exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                      project ([$$132]) [cardinality: 1000000.0, op-cost: 0.0, total-cost: 1000000.0]
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 1000000.0, op-cost: 4000000.0, total-cost: 5000000.0]
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          data-scan []<-[$$132, $$i] <- tpcds.item [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                            exchange
+                                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              empty-tuple-source
+                                              project ([$$131]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- STREAM_PROJECT  |PARTITIONED|
+                                                exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                  data-scan []<-[$$131, $$d] <- tpcds.date_dim [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                  -- DATASOURCE_SCAN  |PARTITIONED|
+                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      project ([$$132]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                      -- STREAM_PROJECT  |PARTITIONED|
+                                        exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          data-scan []<-[$$132, $$i] <- tpcds.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                          -- DATASOURCE_SCAN  |PARTITIONED|
+                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596.plan
index f842d61..c9ca3df 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596.plan
@@ -1,52 +1,52 @@
-distribute result [$$50] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+distribute result [$$50] [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+  exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$50] <- [{"cs1": $$cs1, "cr1": $$cr1, "i1": $$i1}] project: [$$50] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+    assign [$$50] <- [{"cs1": $$cs1, "cr1": $$cr1, "i1": $$i1}] project: [$$50] [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
     -- ASSIGN  |PARTITIONED|
-      project ([$$cs1, $$cr1, $$i1]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+      project ([$$cs1, $$cr1, $$i1]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
         -- SORT_MERGE_EXCHANGE [$$53(ASC), $$54(ASC) ]  |PARTITIONED|
-          order (ASC, $$53) (ASC, $$54) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+          order (ASC, $$53) (ASC, $$54) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
           -- STABLE_SORT [$$53(ASC), $$54(ASC)]  |PARTITIONED|
-            exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+            exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              project ([$$cs1, $$cr1, $$i1, $$53, $$54]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+              project ([$$cs1, $$cr1, $$i1, $$53, $$54]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
               -- STREAM_PROJECT  |PARTITIONED|
-                exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  join (eq($$57, $$53)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 1.1E7]
-                  -- HYBRID_HASH_JOIN [$$53][$$57]  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                    -- HASH_PARTITION_EXCHANGE [$$53]  |PARTITIONED|
-                      project ([$$cs1, $$cr1, $$53, $$54]) [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|
-                          left outer join (and(eq($$54, $$56), eq($$53, $$55))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                          -- HYBRID_HASH_JOIN [$$54, $$53][$$56, $$55]  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              data-scan []<-[$$53, $$54, $$cs1] <- tpcds.catalog_sales [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                              -- DATASOURCE_SCAN  |PARTITIONED|
-                                exchange
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  empty-tuple-source
-                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                            exchange
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              data-scan []<-[$$55, $$56, $$cr1] <- tpcds.catalog_returns [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                              -- DATASOURCE_SCAN  |PARTITIONED|
-                                exchange
-                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  empty-tuple-source
-                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                  left outer join (and(eq($$54, $$56), eq($$53, $$55))) [cardinality: 2.5E11, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
+                  -- HYBRID_HASH_JOIN [$$54, $$53][$$56, $$55]  |PARTITIONED|
+                    exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      data-scan []<-[$$57, $$i1] <- tpcds.item [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                      -- DATASOURCE_SCAN  |PARTITIONED|
-                        exchange
+                      project ([$$cs1, $$i1, $$53, $$54]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                      -- STREAM_PROJECT  |PARTITIONED|
+                        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          empty-tuple-source
+                          join (eq($$57, $$53)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                          -- HYBRID_HASH_JOIN [$$53][$$57]  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                            -- HASH_PARTITION_EXCHANGE [$$53]  |PARTITIONED|
+                              data-scan []<-[$$53, $$54, $$cs1] <- tpcds.catalog_sales [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- DATASOURCE_SCAN  |PARTITIONED|
+                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              data-scan []<-[$$57, $$i1] <- tpcds.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                              -- DATASOURCE_SCAN  |PARTITIONED|
+                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                  -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                    -- HASH_PARTITION_EXCHANGE [$$55]  |PARTITIONED|
+                      data-scan []<-[$$55, $$56, $$cr1] <- tpcds.catalog_returns [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                      -- DATASOURCE_SCAN  |PARTITIONED|
+                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596_ps.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596_ps.plan
index f482266..bf980ad 100644
--- a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596_ps.plan
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/tpcds/query-ASTERIXDB-1596_ps.plan
@@ -1,114 +1,114 @@
-distribute result [$$50] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+distribute result [$$50] [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+  exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$50] <- [{"cs1": $$cs1, "cr1": $$cr1, "i1": $$i1}] project: [$$50] [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+    assign [$$50] <- [{"cs1": $$cs1, "cr1": $$cr1, "i1": $$i1}] project: [$$50] [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
     -- ASSIGN  |PARTITIONED|
-      project ([$$cs1, $$cr1, $$i1]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+      project ([$$cs1, $$cr1, $$i1]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-          order (ASC, $$53) (ASC, $$54) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+          order (ASC, $$53) (ASC, $$54) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
           -- STABLE_SORT [$$53(ASC), $$54(ASC)]  |PARTITIONED|
-            exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+            exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
             -- RANGE_PARTITION_EXCHANGE [$$53(ASC), $$54(ASC)]  |PARTITIONED|
-              forward: shared-variable = $$72 [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+              forward: shared-variable = $$72 [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
               -- FORWARD  |PARTITIONED|
-                exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  replicate [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                  replicate [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                   -- REPLICATE  |PARTITIONED|
-                    exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                    exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      project ([$$cs1, $$cr1, $$i1, $$53, $$54]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                      project ([$$cs1, $$cr1, $$i1, $$53, $$54]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                       -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                        exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          join (eq($$57, $$53)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 1.1E7]
-                          -- HYBRID_HASH_JOIN [$$53][$$57]  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                            -- HASH_PARTITION_EXCHANGE [$$53]  |PARTITIONED|
-                              project ([$$cs1, $$cr1, $$53, $$54]) [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|
-                                  left outer join (and(eq($$54, $$56), eq($$53, $$55))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                  -- HYBRID_HASH_JOIN [$$54, $$53][$$56, $$55]  |PARTITIONED|
-                                    exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      data-scan []<-[$$53, $$54, $$cs1] <- tpcds.catalog_sales [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                      -- DATASOURCE_SCAN  |PARTITIONED|
-                                        exchange
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          empty-tuple-source
-                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                    exchange
-                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      data-scan []<-[$$55, $$56, $$cr1] <- tpcds.catalog_returns [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                      -- DATASOURCE_SCAN  |PARTITIONED|
-                                        exchange
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          empty-tuple-source
-                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                            exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                          left outer join (and(eq($$54, $$56), eq($$53, $$55))) [cardinality: 2.5E11, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
+                          -- HYBRID_HASH_JOIN [$$54, $$53][$$56, $$55]  |PARTITIONED|
+                            exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              data-scan []<-[$$57, $$i1] <- tpcds.item [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                              -- DATASOURCE_SCAN  |PARTITIONED|
-                                exchange
+                              project ([$$cs1, $$i1, $$53, $$54]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                              -- STREAM_PROJECT  |PARTITIONED|
+                                exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  empty-tuple-source
+                                  join (eq($$57, $$53)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                  -- HYBRID_HASH_JOIN [$$53][$$57]  |PARTITIONED|
+                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    -- HASH_PARTITION_EXCHANGE [$$53]  |PARTITIONED|
+                                      data-scan []<-[$$53, $$54, $$cs1] <- tpcds.catalog_sales [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                      -- DATASOURCE_SCAN  |PARTITIONED|
+                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                    exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      data-scan []<-[$$57, $$i1] <- tpcds.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                      -- DATASOURCE_SCAN  |PARTITIONED|
+                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                          -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- HASH_PARTITION_EXCHANGE [$$55]  |PARTITIONED|
+                              data-scan []<-[$$55, $$56, $$cr1] <- tpcds.catalog_returns [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                              -- DATASOURCE_SCAN  |PARTITIONED|
+                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                exchange
+                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                 -- BROADCAST_EXCHANGE  |PARTITIONED|
-                  aggregate [$$72] <- [agg-range-map($$69, $$70, $$71)]
+                  aggregate [$$72] <- [agg-range-map($$69, $$70, $$71)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                   -- AGGREGATE  |UNPARTITIONED|
-                    exchange
+                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-                      aggregate [$$69, $$70, $$71] <- [agg-local-sampling($$53, $$54), agg-null-writer($$53), agg-null-writer($$54)]
+                      aggregate [$$69, $$70, $$71] <- [agg-local-sampling($$53, $$54), agg-null-writer($$53), agg-null-writer($$54)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |PARTITIONED|
-                        project ([$$53, $$54])
+                        project ([$$53, $$54]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- STREAM_PROJECT  |PARTITIONED|
-                          exchange
+                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            replicate [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                            replicate [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                             -- REPLICATE  |PARTITIONED|
-                              exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                              exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                project ([$$cs1, $$cr1, $$i1, $$53, $$54]) [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                                project ([$$cs1, $$cr1, $$i1, $$53, $$54]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                 -- STREAM_PROJECT  |PARTITIONED|
-                                  exchange [cardinality: 5.0E11, op-cost: 0.0, total-cost: 1.1E7]
+                                  exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    join (eq($$57, $$53)) [cardinality: 5.0E11, op-cost: 2000000.0, total-cost: 1.1E7]
-                                    -- HYBRID_HASH_JOIN [$$53][$$57]  |PARTITIONED|
-                                      exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                      -- HASH_PARTITION_EXCHANGE [$$53]  |PARTITIONED|
-                                        project ([$$cs1, $$cr1, $$53, $$54]) [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|
-                                            left outer join (and(eq($$54, $$56), eq($$53, $$55))) [cardinality: 1000000.0, op-cost: 2000000.0, total-cost: 6000000.0]
-                                            -- HYBRID_HASH_JOIN [$$54, $$53][$$56, $$55]  |PARTITIONED|
-                                              exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
-                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                data-scan []<-[$$53, $$54, $$cs1] <- tpcds.catalog_sales [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                -- DATASOURCE_SCAN  |PARTITIONED|
-                                                  exchange
-                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    empty-tuple-source
-                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                              exchange
-                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                data-scan []<-[$$55, $$56, $$cr1] <- tpcds.catalog_returns [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                                -- DATASOURCE_SCAN  |PARTITIONED|
-                                                  exchange
-                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                    empty-tuple-source
-                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                      exchange [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 2000000.0]
+                                    left outer join (and(eq($$54, $$56), eq($$53, $$55))) [cardinality: 2.5E11, doc-size: -3.0, op-cost: 2000000.0, total-cost: 1.1E7]
+                                    -- HYBRID_HASH_JOIN [$$54, $$53][$$56, $$55]  |PARTITIONED|
+                                      exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        data-scan []<-[$$57, $$i1] <- tpcds.item [cardinality: 1000000.0, op-cost: 1000000.0, total-cost: 1000000.0]
-                                        -- DATASOURCE_SCAN  |PARTITIONED|
-                                          exchange
+                                        project ([$$cs1, $$i1, $$53, $$54]) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
+                                        -- STREAM_PROJECT  |PARTITIONED|
+                                          exchange [cardinality: 1000000.0, doc-size: -2.0, op-cost: 0.0, total-cost: 6000000.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            empty-tuple-source
+                                            join (eq($$57, $$53)) [cardinality: 1000000.0, doc-size: -2.0, op-cost: 2000000.0, total-cost: 6000000.0]
+                                            -- HYBRID_HASH_JOIN [$$53][$$57]  |PARTITIONED|
+                                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- HASH_PARTITION_EXCHANGE [$$53]  |PARTITIONED|
+                                                data-scan []<-[$$53, $$54, $$cs1] <- tpcds.catalog_sales [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- DATASOURCE_SCAN  |PARTITIONED|
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                              exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                              -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                data-scan []<-[$$57, $$i1] <- tpcds.item [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 1000000.0]
+                                                -- DATASOURCE_SCAN  |PARTITIONED|
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                    empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                    -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- HASH_PARTITION_EXCHANGE [$$55]  |PARTITIONED|
+                                        data-scan []<-[$$55, $$56, $$cr1] <- tpcds.catalog_returns [cardinality: 1000000.0, doc-size: -1.0, op-cost: 1000000.0, total-cost: 1000000.0]
+                                        -- DATASOURCE_SCAN  |PARTITIONED|
+                                          exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                          -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                            empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.3.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.3.plan
index 0e1cbcc..0cd7199 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.3.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.3.plan
@@ -1,18 +1,18 @@
-distribute result [$$35] [cardinality: 961.01, doc-size: 15.0, op-cost: 0.0, total-cost: 136513.95]
+distribute result [$$35] [cardinality: 960.71, doc-size: 15.0, op-cost: 0.0, total-cost: 136471.34]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 961.01, doc-size: 15.0, op-cost: 0.0, total-cost: 136513.95]
+  exchange [cardinality: 960.71, doc-size: 15.0, op-cost: 0.0, total-cost: 136471.34]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    distinct ([$$35]) [cardinality: 961.01, doc-size: 15.0, op-cost: 0.0, total-cost: 136513.95]
+    distinct ([$$35]) [cardinality: 960.71, doc-size: 15.0, op-cost: 0.0, total-cost: 136471.34]
     -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-      exchange [cardinality: 4785.13, doc-size: 15.0, op-cost: 0.0, total-cost: 78018.88]
+      exchange [cardinality: 4783.64, doc-size: 15.0, op-cost: 0.0, total-cost: 77996.64]
       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-        order (ASC, $$35) [cardinality: 4785.13, doc-size: 15.0, op-cost: 0.0, total-cost: 78018.88]
+        order (ASC, $$35) [cardinality: 4783.64, doc-size: 15.0, op-cost: 0.0, total-cost: 77996.64]
         -- STABLE_SORT [$$35(ASC)]  |PARTITIONED|
-          exchange [cardinality: 4785.13, doc-size: 15.0, op-cost: 0.0, total-cost: 19523.81]
+          exchange [cardinality: 4783.64, doc-size: 15.0, op-cost: 0.0, total-cost: 19521.94]
           -- HASH_PARTITION_EXCHANGE [$$35]  |PARTITIONED|
-            assign [$$35] <- [{"l_linenumber": $$37, "l_partkey": $$l.getField(1), "o_custkey": $$o.getField(1)}] project: [$$35] [cardinality: 4785.13, doc-size: 15.0, op-cost: 0.0, total-cost: 19523.81]
+            assign [$$35] <- [{"l_linenumber": $$37, "l_partkey": $$l.getField(1), "o_custkey": $$o.getField(1)}] project: [$$35] [cardinality: 4783.64, doc-size: 15.0, op-cost: 0.0, total-cost: 19521.94]
             -- ASSIGN  |PARTITIONED|
-              select (gt($$l.getField(4), 10)) [cardinality: 4785.13, doc-size: 15.0, op-cost: 0.0, total-cost: 19523.81]
+              select (gt($$l.getField(4), 10)) [cardinality: 4783.64, doc-size: 15.0, op-cost: 0.0, total-cost: 19521.94]
               -- STREAM_SELECT  |PARTITIONED|
                 project ([$$o, $$37, $$l]) [cardinality: 4779.14, doc-size: 15.0, op-cost: 0.0, total-cost: 6005.0]
                 -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.4.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.4.plan
index c5d57cb..d69e138 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.4.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.4.plan
@@ -1,18 +1,18 @@
-distribute result [$$34] [cardinality: 1400.81, doc-size: 5.0, op-cost: 0.0, total-cost: 166845.41]
+distribute result [$$34] [cardinality: 1400.38, doc-size: 5.0, op-cost: 0.0, total-cost: 166792.72]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 1400.81, doc-size: 5.0, op-cost: 0.0, total-cost: 166845.41]
+  exchange [cardinality: 1400.38, doc-size: 5.0, op-cost: 0.0, total-cost: 166792.72]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    distinct ([$$34]) [cardinality: 1400.81, doc-size: 5.0, op-cost: 0.0, total-cost: 166845.41]
+    distinct ([$$34]) [cardinality: 1400.38, doc-size: 5.0, op-cost: 0.0, total-cost: 166792.72]
     -- PRE_SORTED_DISTINCT_BY  |PARTITIONED|
-      exchange [cardinality: 5882.42, doc-size: 5.0, op-cost: 0.0, total-cost: 93184.61]
+      exchange [cardinality: 5880.6, doc-size: 5.0, op-cost: 0.0, total-cost: 93157.33]
       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-        order (ASC, $$34) [cardinality: 5882.42, doc-size: 5.0, op-cost: 0.0, total-cost: 93184.61]
+        order (ASC, $$34) [cardinality: 5880.6, doc-size: 5.0, op-cost: 0.0, total-cost: 93157.33]
         -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
-          exchange [cardinality: 5882.42, doc-size: 5.0, op-cost: 0.0, total-cost: 19523.81]
+          exchange [cardinality: 5880.6, doc-size: 5.0, op-cost: 0.0, total-cost: 19521.94]
           -- HASH_PARTITION_EXCHANGE [$$34]  |PARTITIONED|
-            assign [$$34] <- [{"l_orderkey": $$36, "o_custkey": $$o.getField(1)}] project: [$$34] [cardinality: 5882.42, doc-size: 5.0, op-cost: 0.0, total-cost: 19523.81]
+            assign [$$34] <- [{"l_orderkey": $$36, "o_custkey": $$o.getField(1)}] project: [$$34] [cardinality: 5880.6, doc-size: 5.0, op-cost: 0.0, total-cost: 19521.94]
             -- ASSIGN  |PARTITIONED|
-              select (gt($$l.getField(1), 5)) project: [$$o, $$36] [cardinality: 5882.42, doc-size: 5.0, op-cost: 0.0, total-cost: 19523.81]
+              select (gt($$l.getField(1), 5)) project: [$$o, $$36] [cardinality: 5880.6, doc-size: 5.0, op-cost: 0.0, total-cost: 19521.94]
               -- STREAM_SELECT  |PARTITIONED|
                 project ([$$o, $$36, $$l]) [cardinality: 5875.07, doc-size: 5.0, op-cost: 0.0, total-cost: 6005.0]
                 -- STREAM_PROJECT  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.5.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.5.plan
index b14e74d..8a11161 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.5.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.5.plan
@@ -1,28 +1,28 @@
-distribute result [$$101] [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 18052.66]
+distribute result [$$101] [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 18037.6]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 18052.66]
+  exchange [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 18037.6]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$101] <- [{"$1": $$111}] project: [$$101] [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 18052.66]
+    assign [$$101] <- [{"$1": $$111}] project: [$$101] [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 18037.6]
     -- ASSIGN  |PARTITIONED|
-      project ([$$111]) [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 18052.66]
+      project ([$$111]) [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 18037.6]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 18052.66]
+        exchange [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 18037.6]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
           group by ([$$l_partkey := $$115; $$o_orderstatus := $$116; $$c_nationkey := $$117]) decor ([]) {
                     aggregate [$$111] <- [sql-sum-serial($$114)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- AGGREGATE  |LOCAL|
                       nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
-                 } [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 18052.66]
+                 } [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 18037.6]
           -- EXTERNAL_GROUP_BY[$$115, $$116, $$117]  |PARTITIONED|
-            exchange [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 12028.83]
+            exchange [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 12021.3]
             -- HASH_PARTITION_EXCHANGE [$$115, $$116, $$117]  |PARTITIONED|
               group by ([$$115 := $$102; $$116 := $$103; $$117 := $$104]) decor ([]) {
                         aggregate [$$114] <- [sql-count-serial(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- AGGREGATE  |LOCAL|
                           nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                     } [cardinality: 1003.97, doc-size: 5.0, op-cost: 0.0, total-cost: 12028.83]
+                     } [cardinality: 1002.74, doc-size: 5.0, op-cost: 0.0, total-cost: 12021.3]
               -- EXTERNAL_GROUP_BY[$$102, $$103, $$104]  |PARTITIONED|
                 exchange [cardinality: 6010.65, doc-size: 5.0, op-cost: 0.0, total-cost: 6005.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -40,7 +40,7 @@
                             -- STREAM_PROJECT  |PARTITIONED|
                               exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                join (eq($$109, $$108)) [cardinality: 1502.82, doc-size: 15.0, op-cost: 2101.41, total-cost: 4351.41]
+                                join (eq($$109, $$108)) [cardinality: 1501.41, doc-size: 15.0, op-cost: 2101.41, total-cost: 4351.41]
                                 -- HYBRID_HASH_JOIN [$$109][$$108]  |PARTITIONED|
                                   exchange [cardinality: 0.0, doc-size: 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/cardinality-estimation/join-queries/join-queries.6.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.6.plan
index 4ef29b2..ceed188 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.6.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.6.plan
@@ -1,36 +1,36 @@
-distribute result [$$101] [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+distribute result [$$101] [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+  exchange [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$101] <- [{"$1": $$111}] project: [$$101] [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+    assign [$$101] <- [{"$1": $$111}] project: [$$101] [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
     -- ASSIGN  |PARTITIONED|
-      project ([$$111]) [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+      project ([$$111]) [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+        exchange [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
           group by ([$$l_linenumber := $$115; $$o_orderstatus := $$116; $$c_nationkey := $$117]) decor ([]) {
                     aggregate [$$111] <- [sql-sum-serial($$114)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- AGGREGATE  |LOCAL|
                       nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
-                 } [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+                 } [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
           -- EXTERNAL_GROUP_BY[$$115, $$116, $$117]  |PARTITIONED|
-            exchange [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 28416.0]
+            exchange [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 28389.65]
             -- HASH_PARTITION_EXCHANGE [$$115, $$116, $$117]  |PARTITIONED|
               group by ([$$115 := $$106; $$116 := $$103; $$117 := $$104]) decor ([]) {
                         aggregate [$$114] <- [sql-count-serial(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- AGGREGATE  |LOCAL|
                           nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                     } [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 28416.0]
+                     } [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 28389.65]
               -- EXTERNAL_GROUP_BY[$$106, $$103, $$104]  |PARTITIONED|
-                exchange [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                exchange [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  project ([$$106, $$103, $$104]) [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                  project ([$$106, $$103, $$104]) [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    exchange [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                    exchange [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      unnest-map [$$105, $$106, $$l] <- index-search("LineItem", 0, "Default", "tpch", "LineItem", true, true, 1, $$107, 1, $$107, true, true, true) [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                      unnest-map [$$105, $$106, $$l] <- index-search("LineItem", 0, "Default", "tpch", "LineItem", true, true, 1, $$107, 1, $$107, true, true, true) [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                       -- BTREE_SEARCH  |PARTITIONED|
                         exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- BROADCAST_EXCHANGE  |PARTITIONED|
@@ -38,7 +38,7 @@
                           -- STREAM_PROJECT  |PARTITIONED|
                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              join (eq($$109, $$108)) [cardinality: 1502.82, doc-size: 15.0, op-cost: 2101.41, total-cost: 4351.41]
+                              join (eq($$109, $$108)) [cardinality: 1501.41, doc-size: 15.0, op-cost: 2101.41, total-cost: 4351.41]
                               -- HYBRID_HASH_JOIN [$$109][$$108]  |PARTITIONED|
                                 exchange [cardinality: 0.0, doc-size: 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/cardinality-estimation/join-queries/join-queries.7.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.7.plan
index e6af8bb..b459ffc 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.7.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.7.plan
@@ -1,36 +1,36 @@
-distribute result [$$101] [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+distribute result [$$101] [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+  exchange [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$101] <- [{"$1": $$111}] project: [$$101] [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+    assign [$$101] <- [{"$1": $$111}] project: [$$101] [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
     -- ASSIGN  |PARTITIONED|
-      project ([$$111]) [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+      project ([$$111]) [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+        exchange [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
           group by ([$$l_linenumber := $$115; $$c_nationkey := $$116; $$o_orderstatus := $$117]) decor ([]) {
                     aggregate [$$111] <- [sql-sum-serial($$114)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- AGGREGATE  |LOCAL|
                       nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- NESTED_TUPLE_SOURCE  |LOCAL|
-                 } [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 34439.83]
+                 } [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 34405.95]
           -- EXTERNAL_GROUP_BY[$$115, $$116, $$117]  |PARTITIONED|
-            exchange [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 28416.0]
+            exchange [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 28389.65]
             -- HASH_PARTITION_EXCHANGE [$$115, $$116, $$117]  |PARTITIONED|
               group by ([$$115 := $$106; $$116 := $$103; $$117 := $$104]) decor ([]) {
                         aggregate [$$114] <- [sql-count-serial(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- AGGREGATE  |LOCAL|
                           nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- NESTED_TUPLE_SOURCE  |LOCAL|
-                     } [cardinality: 1003.97, doc-size: 20.0, op-cost: 0.0, total-cost: 28416.0]
+                     } [cardinality: 1002.74, doc-size: 20.0, op-cost: 0.0, total-cost: 28389.65]
               -- EXTERNAL_GROUP_BY[$$106, $$103, $$104]  |PARTITIONED|
-                exchange [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                exchange [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  project ([$$106, $$103, $$104]) [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                  project ([$$106, $$103, $$104]) [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    exchange [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                    exchange [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      unnest-map [$$105, $$106, $$l] <- index-search("LineItem", 0, "Default", "tpch", "LineItem", true, true, 1, $$107, 1, $$107, true, true, true) [cardinality: 6023.83, doc-size: 20.0, op-cost: 0.0, total-cost: 22392.17]
+                      unnest-map [$$105, $$106, $$l] <- index-search("LineItem", 0, "Default", "tpch", "LineItem", true, true, 1, $$107, 1, $$107, true, true, true) [cardinality: 6016.3, doc-size: 20.0, op-cost: 0.0, total-cost: 22373.35]
                       -- BTREE_SEARCH  |PARTITIONED|
                         exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- BROADCAST_EXCHANGE  |PARTITIONED|
@@ -38,7 +38,7 @@
                           -- STREAM_PROJECT  |PARTITIONED|
                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              join (eq($$109, $$108)) [cardinality: 1502.82, doc-size: 15.0, op-cost: 2101.41, total-cost: 4351.41]
+                              join (eq($$109, $$108)) [cardinality: 1501.41, doc-size: 15.0, op-cost: 2101.41, total-cost: 4351.41]
                               -- HYBRID_HASH_JOIN [$$109][$$108]  |PARTITIONED|
                                 exchange [cardinality: 0.0, doc-size: 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/cardinality-estimation/join-queries/join-queries.8.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.8.plan
index 9f61a1e..ee29dcd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.8.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/cardinality-estimation/join-queries/join-queries.8.plan
@@ -1,42 +1,42 @@
-distribute result [$$119] [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6746.57]
+distribute result [$$119] [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6741.88]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6746.57]
+  exchange [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6741.88]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$119] <- [{"n_name": $$n_name, "revenue": $$132}] project: [$$119] [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6746.57]
+    assign [$$119] <- [{"n_name": $$n_name, "revenue": $$132}] project: [$$119] [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6741.88]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6746.57]
+      exchange [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6741.88]
       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
         group by ([$$n_name := $$142]) decor ([]) {
                   aggregate [$$132] <- [global-sql-sum-serial($$141)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                   -- AGGREGATE  |LOCAL|
                     nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-               } [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6746.57]
+               } [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6741.88]
         -- EXTERNAL_GROUP_BY[$$142]  |PARTITIONED|
-          exchange [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6708.01]
+          exchange [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6703.4]
           -- HASH_PARTITION_EXCHANGE [$$142]  |PARTITIONED|
             group by ([$$142 := $$120]) decor ([]) {
                       aggregate [$$141] <- [local-sql-sum-serial(numeric-multiply($$139, numeric-subtract(1, $$140)))] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
                         nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   } [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6708.01]
+                   } [cardinality: 25.0, doc-size: 45.0, op-cost: 0.0, total-cost: 6703.4]
             -- EXTERNAL_GROUP_BY[$$120]  |PARTITIONED|
-              exchange [cardinality: 38.56, doc-size: 45.0, op-cost: 0.0, total-cost: 6669.45]
+              exchange [cardinality: 38.48, doc-size: 45.0, op-cost: 0.0, total-cost: 6664.92]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                project ([$$139, $$140, $$120]) [cardinality: 38.56, doc-size: 45.0, op-cost: 0.0, total-cost: 6669.45]
+                project ([$$139, $$140, $$120]) [cardinality: 38.48, doc-size: 45.0, op-cost: 0.0, total-cost: 6664.92]
                 -- STREAM_PROJECT  |PARTITIONED|
-                  exchange [cardinality: 38.56, doc-size: 45.0, op-cost: 0.0, total-cost: 6669.45]
+                  exchange [cardinality: 38.48, doc-size: 45.0, op-cost: 0.0, total-cost: 6664.92]
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    join (eq($$130, $$128)) [cardinality: 38.56, doc-size: 45.0, op-cost: 63.56, total-cost: 6669.45]
+                    join (eq($$130, $$128)) [cardinality: 38.48, doc-size: 45.0, op-cost: 63.48, total-cost: 6664.92]
                     -- HYBRID_HASH_JOIN [$$130][$$128]  |PARTITIONED|
-                      exchange [cardinality: 38.56, doc-size: 40.0, op-cost: 0.0, total-cost: 6517.32]
+                      exchange [cardinality: 38.48, doc-size: 40.0, op-cost: 0.0, total-cost: 6512.96]
                       -- HASH_PARTITION_EXCHANGE [$$130]  |PARTITIONED|
-                        project ([$$139, $$140, $$130]) [cardinality: 38.56, doc-size: 40.0, op-cost: 0.0, total-cost: 6517.32]
+                        project ([$$139, $$140, $$130]) [cardinality: 38.48, doc-size: 40.0, op-cost: 0.0, total-cost: 6512.96]
                         -- STREAM_PROJECT  |PARTITIONED|
-                          exchange [cardinality: 38.56, doc-size: 40.0, op-cost: 0.0, total-cost: 6517.32]
+                          exchange [cardinality: 38.48, doc-size: 40.0, op-cost: 0.0, total-cost: 6512.96]
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            join (and(eq($$133, $$127), eq($$130, $$131))) [cardinality: 38.56, doc-size: 40.0, op-cost: 1036.42, total-cost: 6517.32]
+                            join (and(eq($$133, $$127), eq($$130, $$131))) [cardinality: 38.48, doc-size: 40.0, op-cost: 1035.18, total-cost: 6512.96]
                             -- HYBRID_HASH_JOIN [$$133, $$131][$$127, $$130]  |PARTITIONED|
                               exchange [cardinality: 6010.65, doc-size: 10.0, op-cost: 0.0, total-cost: 6005.0]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -54,7 +54,7 @@
                                           -- STREAM_PROJECT  |PARTITIONED|
                                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              join (eq($$123, $$136)) [cardinality: 248.59, doc-size: 20.0, op-cost: 398.35, total-cost: 2446.71]
+                                              join (eq($$123, $$136)) [cardinality: 248.35, doc-size: 20.0, op-cost: 398.35, total-cost: 2446.71]
                                               -- HYBRID_HASH_JOIN [$$136][$$123]  |PARTITIONED|
                                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                 -- HASH_PARTITION_EXCHANGE [$$136]  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/pushdown/field-access-pushdown/field-access-pushdown.008.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/pushdown/field-access-pushdown/field-access-pushdown.008.plan
index ff1702c..feb6c7f 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/pushdown/field-access-pushdown/field-access-pushdown.008.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/column/pushdown/field-access-pushdown/field-access-pushdown.008.plan
@@ -1,22 +1,22 @@
-distribute result [$$31] [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 47.25]
+distribute result [$$31] [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 64.65]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 47.25]
+  exchange [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 64.65]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$31] <- [{"age": $$38, "name": $$39}] project: [$$31] [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 47.25]
+    assign [$$31] <- [{"age": $$38, "name": $$39}] project: [$$31] [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 64.65]
     -- ASSIGN  |PARTITIONED|
-      project ([$$38, $$39]) [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 47.25]
+      project ([$$38, $$39]) [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 64.65]
       -- STREAM_PROJECT  |PARTITIONED|
-        exchange [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 47.25]
+        exchange [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 64.65]
         -- SORT_MERGE_EXCHANGE [$$34(ASC) ]  |PARTITIONED|
-          order (ASC, $$34) [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 47.25]
+          order (ASC, $$34) [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 64.65]
           -- STABLE_SORT [$$34(ASC)]  |PARTITIONED|
-            exchange [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 45.0]
+            exchange [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 45.0]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              project ([$$38, $$39, $$34]) [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 45.0]
+              project ([$$38, $$39, $$34]) [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 45.0]
               -- STREAM_PROJECT  |PARTITIONED|
-                exchange [cardinality: 2.1, doc-size: 33.5, op-cost: 0.0, total-cost: 45.0]
+                exchange [cardinality: 7.0, doc-size: 33.5, op-cost: 0.0, total-cost: 45.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  join (eq($$33, $$34)) [cardinality: 2.1, doc-size: 33.5, op-cost: 15.0, total-cost: 45.0]
+                  join (eq($$33, $$34)) [cardinality: 7.0, doc-size: 33.5, op-cost: 15.0, total-cost: 45.0]
                   -- HYBRID_HASH_JOIN [$$34][$$33]  |PARTITIONED|
                     exchange [cardinality: 8.0, doc-size: 15.5, op-cost: 0.0, total-cost: 8.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.06.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.06.plan
index a03384c..fdad6dd 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.06.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.06.plan
@@ -1,20 +1,20 @@
-distribute result [$$36] [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 98061.73]
+distribute result [$$36] [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22537.15]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 98061.73]
+  exchange [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22537.15]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$36] <- [{"o_orderkey": $$43, "l_orderkey": $$44, "l_suppkey": $$42}] project: [$$36] [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 98061.73]
+    assign [$$36] <- [{"o_orderkey": $$43, "l_orderkey": $$44, "l_suppkey": $$42}] project: [$$36] [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22537.15]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 98061.73]
+      exchange [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22537.15]
       -- SORT_MERGE_EXCHANGE [$$43(ASC), $$44(ASC), $$42(ASC) ]  |PARTITIONED|
-        order (ASC, $$43) (ASC, $$44) (ASC, $$42) [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 98061.73]
+        order (ASC, $$43) (ASC, $$44) (ASC, $$42) [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22537.15]
         -- STABLE_SORT [$$43(ASC), $$44(ASC), $$42(ASC)]  |PARTITIONED|
-          exchange [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 22529.12]
+          exchange [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22529.12]
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-            project ([$$43, $$44, $$42]) [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 22529.12]
+            project ([$$43, $$44, $$42]) [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22529.12]
             -- STREAM_PROJECT  |PARTITIONED|
-              exchange [cardinality: 6016.3, doc-size: 15.0, op-cost: 0.0, total-cost: 22529.12]
+              exchange [cardinality: 4.01, doc-size: 15.0, op-cost: 0.0, total-cost: 22529.12]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                join (and(eq($$43, $$44), eq($$49, $$42))) [cardinality: 6016.3, doc-size: 15.0, op-cost: 7512.06, total-cost: 22529.12]
+                join (and(eq($$43, $$44), eq($$49, $$42))) [cardinality: 4.01, doc-size: 15.0, op-cost: 7512.06, total-cost: 22529.12]
                 -- HYBRID_HASH_JOIN [$$44, $$42][$$43, $$49]  |PARTITIONED|
                   exchange [cardinality: 6005.0, doc-size: 10.0, op-cost: 0.0, total-cost: 6005.0]
                   -- HASH_PARTITION_EXCHANGE [$$44]  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.08.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.08.plan
index 9e6d08b..a5cddf0 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.08.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/join/hash-join-with-redundant-variable/hash-join-with-redundant-variable.08.plan
@@ -1,12 +1,12 @@
-distribute result [$$38] [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 77032.61]
+distribute result [$$38] [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1508.03]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 77032.61]
+  exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1508.03]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$38] <- [{"o_orderkey": $$43, "l_orderkey": $$44, "l_suppkey": $$47}] project: [$$38] [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 77032.61]
+    assign [$$38] <- [{"o_orderkey": $$43, "l_orderkey": $$44, "l_suppkey": $$47}] project: [$$38] [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1508.03]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 77032.61]
+      exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1508.03]
       -- SORT_MERGE_EXCHANGE [$$43(ASC), $$44(ASC), $$47(ASC) ]  |PARTITIONED|
-        order (ASC, $$43) (ASC, $$44) (ASC, $$47) [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 77032.61]
+        order (ASC, $$43) (ASC, $$44) (ASC, $$47) [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1508.03]
         -- STABLE_SORT [$$43(ASC), $$44(ASC), $$47(ASC)]  |PARTITIONED|
           exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1500.0]
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -14,7 +14,7 @@
             -- STREAM_PROJECT  |PARTITIONED|
               exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1500.0]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                left outer join (and(eq($$43, $$44), eq($$56, $$47))) [cardinality: 6016.3, doc-size: 15.0, op-cost: 7512.06, total-cost: 22529.12]
+                left outer join (and(eq($$43, $$44), eq($$56, $$47))) [cardinality: 4.01, doc-size: 15.0, op-cost: 7512.06, total-cost: 22529.12]
                 -- HYBRID_HASH_JOIN [$$43, $$56][$$44, $$47]  |PARTITIONED|
                   exchange [cardinality: 1500.0, doc-size: 5.0, op-cost: 0.0, total-cost: 1500.0]
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.04.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.04.plan
index 1ce1f27..b54781e 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.04.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.04.plan
@@ -38,11 +38,11 @@
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                       join (and(eq($$250, $$203), eq($$202, $$231))) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- HYBRID_HASH_JOIN [$$250, $$231][$$203, $$202]  |PARTITIONED|
-                                        exchange [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                        exchange [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          assign [$$231] <- [get-item($$181, 0)] project: [$$250, $$244, $$231] [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                          assign [$$231] <- [get-item($$181, 0)] project: [$$250, $$244, $$231] [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                           -- ASSIGN  |PARTITIONED|
-                                            exchange [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                            exchange [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               group by ([$$250 := $$200]) decor ([$$244]) {
                                                         aggregate [$$181] <- [listify($$215)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
@@ -51,19 +51,19 @@
                                                           -- AGGREGATE  |LOCAL|
                                                             nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                                                     } [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                                     } [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                               -- PRE_CLUSTERED_GROUP_BY[$$200]  |PARTITIONED|
-                                                exchange [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                                exchange [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  order (ASC, $$200) [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                                  order (ASC, $$200) [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                                   -- STABLE_SORT [$$200(ASC)]  |PARTITIONED|
-                                                    exchange [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                                    exchange [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                                     -- HASH_PARTITION_EXCHANGE [$$200]  |PARTITIONED|
-                                                      project ([$$244, $$208, $$200]) [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                                      project ([$$244, $$208, $$200]) [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                                       -- STREAM_PROJECT  |PARTITIONED|
-                                                        exchange [cardinality: 29.05, doc-size: 61.0, op-cost: 0.0, total-cost: 264469.8]
+                                                        exchange [cardinality: 29.77, doc-size: 61.0, op-cost: 0.0, total-cost: 264474.85]
                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                          join (and(eq($$218, $$213), eq($$223, $$212))) [cardinality: 29.05, doc-size: 61.0, op-cost: 172.16, total-cost: 264469.8]
+                                                          join (and(eq($$218, $$213), eq($$223, $$212))) [cardinality: 29.77, doc-size: 61.0, op-cost: 173.84, total-cost: 264474.85]
                                                           -- HYBRID_HASH_JOIN [$$213, $$223][$$218, $$212]  |PARTITIONED|
                                                             exchange [cardinality: 987.0, doc-size: 10.0, op-cost: 0.0, total-cost: 1000.0]
                                                             -- HASH_PARTITION_EXCHANGE [$$223]  |PARTITIONED|
@@ -169,13 +169,13 @@
                                                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                                           empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                           -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                        exchange [cardinality: 78142.08, doc-size: 147.18, op-cost: 0.0, total-cost: 168971.26]
+                                        exchange [cardinality: 79034.28, doc-size: 147.18, op-cost: 0.0, total-cost: 168971.26]
                                         -- HASH_PARTITION_EXCHANGE [$$203]  |PARTITIONED|
-                                          project ([$$237, $$239, $$245, $$246, $$247, $$225, $$203, $$202]) [cardinality: 78142.08, doc-size: 147.18, op-cost: 0.0, total-cost: 168971.26]
+                                          project ([$$237, $$239, $$245, $$246, $$247, $$225, $$203, $$202]) [cardinality: 79034.28, doc-size: 147.18, op-cost: 0.0, total-cost: 168971.26]
                                           -- STREAM_PROJECT  |PARTITIONED|
-                                            exchange [cardinality: 78142.08, doc-size: 147.18, op-cost: 0.0, total-cost: 168971.26]
+                                            exchange [cardinality: 79034.28, doc-size: 147.18, op-cost: 0.0, total-cost: 168971.26]
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              join (eq($$201, $$204)) [cardinality: 78142.08, doc-size: 147.18, op-cost: 84023.26, total-cost: 168971.26]
+                                              join (eq($$201, $$204)) [cardinality: 79034.28, doc-size: 147.18, op-cost: 84023.26, total-cost: 168971.26]
                                               -- HYBRID_HASH_JOIN [$$204][$$201]  |PARTITIONED|
                                                 exchange [cardinality: 80000.0, doc-size: 10.0, op-cost: 0.0, total-cost: 80000.0]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.05.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.05.plan
index bcc2234..225fdf9 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.05.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.05.plan
@@ -1,44 +1,44 @@
-distribute result [$$122] [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+distribute result [$$122] [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+  exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    limit 10 [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+    limit 10 [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
     -- STREAM_LIMIT  |UNPARTITIONED|
-      assign [$$122] <- [{"$1": 3, "l_orderkey": $$l_orderkey, "revenue": $$134, "o_orderdate": $$o_orderdate, "o_shippriority": $$o_shippriority}] project: [$$122] [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+      assign [$$122] <- [{"$1": 3, "l_orderkey": $$l_orderkey, "revenue": $$134, "o_orderdate": $$o_orderdate, "o_shippriority": $$o_shippriority}] project: [$$122] [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
       -- ASSIGN  |PARTITIONED|
-        exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+        exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
         -- SORT_MERGE_EXCHANGE [$$134(DESC), $$o_orderdate(ASC) ]  |PARTITIONED|
-          limit 10 [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+          limit 10 [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
           -- STREAM_LIMIT  |PARTITIONED|
-            exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+            exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              order (topK: 10) (DESC, $$134) (ASC, $$o_orderdate) [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+              order (topK: 10) (DESC, $$134) (ASC, $$o_orderdate) [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
               -- STABLE_SORT [topK: 10] [$$134(DESC), $$o_orderdate(ASC)]  |PARTITIONED|
-                exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+                exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                   group by ([$$l_orderkey := $$142; $$o_orderdate := $$143; $$o_shippriority := $$144]) decor ([]) {
                             aggregate [$$134] <- [global-sql-sum-serial($$141)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- AGGREGATE  |LOCAL|
                               nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- NESTED_TUPLE_SOURCE  |LOCAL|
-                         } [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1353253.2]
+                         } [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1353243.22]
                   -- EXTERNAL_GROUP_BY[$$142, $$143, $$144]  |PARTITIONED|
-                    exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1322675.66]
+                    exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1322667.4]
                     -- HASH_PARTITION_EXCHANGE [$$142, $$143, $$144]  |PARTITIONED|
                       group by ([$$142 := $$131; $$143 := $$127; $$144 := $$125]) decor ([]) {
                                 aggregate [$$141] <- [local-sql-sum-serial(numeric-multiply($$139, numeric-subtract(1, $$140)))] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- AGGREGATE  |LOCAL|
                                   nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
-                             } [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1322675.66]
+                             } [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1322667.4]
                       -- EXTERNAL_GROUP_BY[$$131, $$127, $$125]  |PARTITIONED|
-                        exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1292098.12]
+                        exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1292091.58]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          project ([$$139, $$140, $$131, $$127, $$125]) [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1292098.12]
+                          project ([$$139, $$140, $$131, $$127, $$125]) [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1292091.58]
                           -- STREAM_PROJECT  |PARTITIONED|
-                            exchange [cardinality: 30577.54, doc-size: 20.0, op-cost: 0.0, total-cost: 1292098.12]
+                            exchange [cardinality: 30575.82, doc-size: 20.0, op-cost: 0.0, total-cost: 1292091.58]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              join (eq($$131, $$129)) [cardinality: 30577.54, doc-size: 20.0, op-cost: 369779.81, total-cost: 1292098.12]
+                              join (eq($$131, $$129)) [cardinality: 30575.82, doc-size: 20.0, op-cost: 369776.53, total-cost: 1292091.58]
                               -- HYBRID_HASH_JOIN [$$131][$$129]  |PARTITIONED|
                                 exchange [cardinality: 310738.1, doc-size: 5.0, op-cost: 0.0, total-cost: 600572.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -56,13 +56,13 @@
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                exchange [cardinality: 14760.43, doc-size: 15.0, op-cost: 0.0, total-cost: 262704.61]
+                                exchange [cardinality: 14759.61, doc-size: 15.0, op-cost: 0.0, total-cost: 262704.61]
                                 -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                  project ([$$127, $$125, $$129]) [cardinality: 14760.43, doc-size: 15.0, op-cost: 0.0, total-cost: 262704.61]
+                                  project ([$$127, $$125, $$129]) [cardinality: 14759.61, doc-size: 15.0, op-cost: 0.0, total-cost: 262704.61]
                                   -- STREAM_PROJECT  |PARTITIONED|
-                                    exchange [cardinality: 14760.43, doc-size: 15.0, op-cost: 0.0, total-cost: 262704.61]
+                                    exchange [cardinality: 14759.61, doc-size: 15.0, op-cost: 0.0, total-cost: 262704.61]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      join (eq($$128, $$136)) [cardinality: 14760.43, doc-size: 15.0, op-cost: 85682.03, total-cost: 262704.61]
+                                      join (eq($$128, $$136)) [cardinality: 14759.61, doc-size: 15.0, op-cost: 85682.03, total-cost: 262704.61]
                                       -- HYBRID_HASH_JOIN [$$136][$$128]  |PARTITIONED|
                                         exchange [cardinality: 73659.45, doc-size: 10.0, op-cost: 0.0, total-cost: 150000.0]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.07.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.07.plan
index c7309eb..e281064 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.07.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.07.plan
@@ -1,46 +1,46 @@
-distribute result [$$149] [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552822.75]
+distribute result [$$149] [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554876.05]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552822.75]
+  exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554876.05]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$149] <- [{"$1": 5, "n_name": $$n_name, "revenue": $$165}] project: [$$149] [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552822.75]
+    assign [$$149] <- [{"$1": 5, "n_name": $$n_name, "revenue": $$165}] project: [$$149] [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554876.05]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552822.75]
+      exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554876.05]
       -- SORT_MERGE_EXCHANGE [$$165(DESC) ]  |PARTITIONED|
-        order (DESC, $$165) [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552822.75]
+        order (DESC, $$165) [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554876.05]
         -- STABLE_SORT [$$165(DESC)]  |PARTITIONED|
-          exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552706.65]
+          exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554759.95]
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
             group by ([$$n_name := $$176]) decor ([]) {
                       aggregate [$$165] <- [global-sql-sum-serial($$175)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
                         nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   } [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1552706.65]
+                   } [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1554759.95]
             -- EXTERNAL_GROUP_BY[$$176]  |PARTITIONED|
-              exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1520025.65]
+              exchange [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1521015.48]
               -- HASH_PARTITION_EXCHANGE [$$176]  |PARTITIONED|
                 group by ([$$176 := $$150]) decor ([]) {
                           aggregate [$$175] <- [local-sql-sum-serial(numeric-multiply($$173, numeric-subtract(1, $$174)))] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- AGGREGATE  |LOCAL|
                             nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                       } [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1520025.65]
+                       } [cardinality: 25.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1521015.48]
                 -- EXTERNAL_GROUP_BY[$$150]  |PARTITIONED|
-                  exchange [cardinality: 32681.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1487344.65]
+                  exchange [cardinality: 33744.47, doc-size: 55.0, op-cost: 0.0, total-cost: 1487271.01]
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    project ([$$173, $$174, $$150]) [cardinality: 32681.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1487344.65]
+                    project ([$$173, $$174, $$150]) [cardinality: 33744.47, doc-size: 55.0, op-cost: 0.0, total-cost: 1487271.01]
                     -- STREAM_PROJECT  |PARTITIONED|
-                      exchange [cardinality: 32681.0, doc-size: 55.0, op-cost: 0.0, total-cost: 1487344.65]
+                      exchange [cardinality: 33744.47, doc-size: 55.0, op-cost: 0.0, total-cost: 1487271.01]
                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                        join (and(eq($$154, $$160), eq($$170, $$159))) [cardinality: 32681.0, doc-size: 55.0, op-cost: 21059.51, total-cost: 1487344.65]
+                        join (and(eq($$154, $$160), eq($$170, $$159))) [cardinality: 33744.47, doc-size: 55.0, op-cost: 21042.46, total-cost: 1487271.01]
                         -- HYBRID_HASH_JOIN [$$160, $$170][$$154, $$159]  |PARTITIONED|
-                          exchange [cardinality: 17111.51, doc-size: 45.0, op-cost: 0.0, total-cost: 1461337.14]
+                          exchange [cardinality: 17094.46, doc-size: 45.0, op-cost: 0.0, total-cost: 1461280.55]
                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                            project ([$$173, $$174, $$150, $$160, $$170]) [cardinality: 17111.51, doc-size: 45.0, op-cost: 0.0, total-cost: 1461337.14]
+                            project ([$$173, $$174, $$150, $$160, $$170]) [cardinality: 17094.46, doc-size: 45.0, op-cost: 0.0, total-cost: 1461280.55]
                             -- STREAM_PROJECT  |PARTITIONED|
-                              exchange [cardinality: 17111.51, doc-size: 45.0, op-cost: 0.0, total-cost: 1461337.14]
+                              exchange [cardinality: 17094.46, doc-size: 45.0, op-cost: 0.0, total-cost: 1461280.55]
                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                join (eq($$158, $$156)) [cardinality: 17111.51, doc-size: 45.0, op-cost: 618216.11, total-cost: 1461337.14]
+                                join (eq($$158, $$156)) [cardinality: 17094.46, doc-size: 45.0, op-cost: 618199.11, total-cost: 1461280.55]
                                 -- HYBRID_HASH_JOIN [$$158][$$156]  |PARTITIONED|
                                   exchange [cardinality: 600572.0, doc-size: 10.0, op-cost: 0.0, total-cost: 600572.0]
                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -56,13 +56,13 @@
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                  exchange [cardinality: 4269.78, doc-size: 35.0, op-cost: 0.0, total-cost: 225469.91]
+                                  exchange [cardinality: 4265.53, doc-size: 35.0, op-cost: 0.0, total-cost: 225447.31]
                                   -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                    project ([$$150, $$160, $$156]) [cardinality: 4269.78, doc-size: 35.0, op-cost: 0.0, total-cost: 225469.91]
+                                    project ([$$150, $$160, $$156]) [cardinality: 4265.53, doc-size: 35.0, op-cost: 0.0, total-cost: 225447.31]
                                     -- STREAM_PROJECT  |PARTITIONED|
-                                      exchange [cardinality: 4269.78, doc-size: 35.0, op-cost: 0.0, total-cost: 225469.91]
+                                      exchange [cardinality: 4265.53, doc-size: 35.0, op-cost: 0.0, total-cost: 225447.31]
                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        join (eq($$155, $$167)) [cardinality: 4269.78, doc-size: 35.0, op-cost: 33330.21, total-cost: 225469.91]
+                                        join (eq($$155, $$167)) [cardinality: 4265.53, doc-size: 35.0, op-cost: 33318.91, total-cost: 225447.31]
                                         -- HYBRID_HASH_JOIN [$$167][$$155]  |PARTITIONED|
                                           exchange [cardinality: 21307.62, doc-size: 10.0, op-cost: 0.0, total-cost: 150000.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -78,13 +78,13 @@
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                       empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                       -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                          exchange [cardinality: 3005.65, doc-size: 25.0, op-cost: 0.0, total-cost: 30117.11]
+                                          exchange [cardinality: 3002.82, doc-size: 25.0, op-cost: 0.0, total-cost: 30117.11]
                                           -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                            project ([$$150, $$160, $$155]) [cardinality: 3005.65, doc-size: 25.0, op-cost: 0.0, total-cost: 30117.11]
+                                            project ([$$150, $$160, $$155]) [cardinality: 3002.82, doc-size: 25.0, op-cost: 0.0, total-cost: 30117.11]
                                             -- STREAM_PROJECT  |PARTITIONED|
-                                              exchange [cardinality: 3005.65, doc-size: 25.0, op-cost: 0.0, total-cost: 30117.11]
+                                              exchange [cardinality: 3002.82, doc-size: 25.0, op-cost: 0.0, total-cost: 30117.11]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                join (eq($$153, $$160)) [cardinality: 3005.65, doc-size: 25.0, op-cost: 15034.11, total-cost: 30117.11]
+                                                join (eq($$153, $$160)) [cardinality: 3002.82, doc-size: 25.0, op-cost: 15034.11, total-cost: 30117.11]
                                                 -- HYBRID_HASH_JOIN [$$153][$$160]  |PARTITIONED|
                                                   exchange [cardinality: 15000.0, doc-size: 10.0, op-cost: 0.0, total-cost: 15000.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.08.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.08.plan
index 7de0f98..6fa60d8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.08.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.08.plan
@@ -1,40 +1,40 @@
-distribute result [$$186] [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981839.91]
+distribute result [$$186] [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986821.79]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981839.91]
+  exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986821.79]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$186] <- [{"$1": 7, "supp_nation": $$supp_nation, "cust_nation": $$cust_nation, "l_year": $$l_year, "revenue": $$200}] project: [$$186] [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981839.91]
+    assign [$$186] <- [{"$1": 7, "supp_nation": $$supp_nation, "cust_nation": $$cust_nation, "l_year": $$l_year, "revenue": $$200}] project: [$$186] [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986821.79]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981839.91]
+      exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986821.79]
       -- SORT_MERGE_EXCHANGE [$$supp_nation(ASC), $$cust_nation(ASC), $$l_year(ASC) ]  |PARTITIONED|
-        order (ASC, $$supp_nation) (ASC, $$cust_nation) (ASC, $$l_year) [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981839.91]
+        order (ASC, $$supp_nation) (ASC, $$cust_nation) (ASC, $$l_year) [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986821.79]
         -- STABLE_SORT [$$supp_nation(ASC), $$cust_nation(ASC), $$l_year(ASC)]  |PARTITIONED|
-          exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981836.55]
+          exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986818.43]
           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
             group by ([$$supp_nation := $$217; $$cust_nation := $$218; $$l_year := $$219]) decor ([]) {
                       aggregate [$$200] <- [global-sql-sum-serial($$216)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
                         nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   } [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981836.55]
+                   } [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986818.43]
             -- EXTERNAL_GROUP_BY[$$217, $$218, $$219]  |PARTITIONED|
-              exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981284.14]
+              exchange [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986248.58]
               -- HASH_PARTITION_EXCHANGE [$$217, $$218, $$219]  |PARTITIONED|
                 group by ([$$217 := $$191; $$218 := $$192; $$219 := $$214]) decor ([]) {
                           aggregate [$$216] <- [local-sql-sum-serial($$184)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                           -- AGGREGATE  |LOCAL|
                             nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- NESTED_TUPLE_SOURCE  |LOCAL|
-                       } [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 981284.14]
+                       } [cardinality: 2.52, doc-size: 68.16, op-cost: 0.0, total-cost: 986248.58]
                 -- EXTERNAL_GROUP_BY[$$191, $$192, $$214]  |PARTITIONED|
-                  exchange [cardinality: 552.41, doc-size: 68.16, op-cost: 0.0, total-cost: 980731.73]
+                  exchange [cardinality: 569.85, doc-size: 68.16, op-cost: 0.0, total-cost: 985678.73]
                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                    assign [$$184, $$214] <- [numeric-multiply($$211, numeric-subtract(1, $$212)), get-year(date($$190))] project: [$$184, $$191, $$192, $$214] [cardinality: 552.41, doc-size: 68.16, op-cost: 0.0, total-cost: 980731.73]
+                    assign [$$184, $$214] <- [numeric-multiply($$211, numeric-subtract(1, $$212)), get-year(date($$190))] project: [$$184, $$191, $$192, $$214] [cardinality: 569.85, doc-size: 68.16, op-cost: 0.0, total-cost: 985678.73]
                     -- ASSIGN  |PARTITIONED|
-                      project ([$$191, $$192, $$211, $$212, $$190]) [cardinality: 552.41, doc-size: 68.16, op-cost: 0.0, total-cost: 980731.73]
+                      project ([$$191, $$192, $$211, $$212, $$190]) [cardinality: 569.85, doc-size: 68.16, op-cost: 0.0, total-cost: 985678.73]
                       -- STREAM_PROJECT  |PARTITIONED|
-                        exchange [cardinality: 552.41, doc-size: 68.16, op-cost: 0.0, total-cost: 980731.73]
+                        exchange [cardinality: 569.85, doc-size: 68.16, op-cost: 0.0, total-cost: 985678.73]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          join (and(eq($$201, $$199), eq($$197, $$210))) [cardinality: 552.41, doc-size: 68.16, op-cost: 28797.6, total-cost: 980731.73]
+                          join (and(eq($$201, $$199), eq($$197, $$210))) [cardinality: 569.85, doc-size: 68.16, op-cost: 29246.91, total-cost: 985678.73]
                           -- HYBRID_HASH_JOIN [$$199, $$210][$$201, $$197]  |PARTITIONED|
                             exchange [cardinality: 150141.11, doc-size: 10.0, op-cost: 0.0, total-cost: 150000.0]
                             -- HASH_PARTITION_EXCHANGE [$$210]  |PARTITIONED|
@@ -56,7 +56,7 @@
                                             -- STREAM_PROJECT  |PARTITIONED|
                                               exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                join (eq($$193, $$204)) [cardinality: 13770.52, doc-size: 48.16, op-cost: 180539.58, total-cost: 784201.87]
+                                                join (eq($$193, $$204)) [cardinality: 14219.43, doc-size: 48.16, op-cost: 180543.69, total-cost: 784210.07]
                                                 -- HYBRID_HASH_JOIN [$$204][$$193]  |PARTITIONED|
                                                   exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -80,7 +80,7 @@
                                                     -- STREAM_PROJECT  |PARTITIONED|
                                                       exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                        join (eq($$205, $$198)) [cardinality: 77.87, doc-size: 38.16, op-cost: 995.4, total-cost: 2778.8]
+                                                        join (eq($$205, $$198)) [cardinality: 78.9, doc-size: 38.16, op-cost: 995.4, total-cost: 2778.8]
                                                         -- HYBRID_HASH_JOIN [$$205][$$198]  |PARTITIONED|
                                                           exchange [cardinality: 0.0, doc-size: 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/tpch/query-plans/query-plans.09.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.09.plan
index daa0f04..efb7af8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.09.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.09.plan
@@ -1,36 +1,36 @@
-distribute result [$$199] [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258937.81]
+distribute result [$$199] [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258952.06]
 -- DISTRIBUTE_RESULT  |PARTITIONED|
-  exchange [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258937.81]
+  exchange [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258952.06]
   -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-    assign [$$199] <- [{"$1": 8, "o_year": $$o_year, "mkt_share": numeric-divide($$214, $$215)}] project: [$$199] [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258937.81]
+    assign [$$199] <- [{"$1": 8, "o_year": $$o_year, "mkt_share": numeric-divide($$214, $$215)}] project: [$$199] [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258952.06]
     -- ASSIGN  |PARTITIONED|
-      exchange [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258937.81]
+      exchange [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258952.06]
       -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
         group by ([$$o_year := $$238]) decor ([]) {
                   aggregate [$$214, $$215] <- [global-sql-sum-serial($$236), global-sql-sum-serial($$237)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                   -- AGGREGATE  |LOCAL|
                     nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- NESTED_TUPLE_SOURCE  |LOCAL|
-               } [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258937.81]
+               } [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258952.06]
         -- EXTERNAL_GROUP_BY[$$238]  |PARTITIONED|
-          exchange [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258777.32]
+          exchange [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258786.5]
           -- HASH_PARTITION_EXCHANGE [$$238]  |PARTITIONED|
             group by ([$$238 := $$200]) decor ([]) {
                       aggregate [$$236, $$237] <- [local-sql-sum-serial(switch-case(true, eq($$232, "PERU"), numeric-multiply($$230, numeric-subtract(1, $$231)), 0)), local-sql-sum-serial(numeric-multiply($$230, numeric-subtract(1, $$231)))] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                       -- AGGREGATE  |LOCAL|
                         nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- NESTED_TUPLE_SOURCE  |LOCAL|
-                   } [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258777.32]
+                   } [cardinality: 2.0, doc-size: 70.0, op-cost: 0.0, total-cost: 1258786.5]
             -- EXTERNAL_GROUP_BY[$$200]  |PARTITIONED|
-              exchange [cardinality: 160.49, doc-size: 70.0, op-cost: 0.0, total-cost: 1258616.83]
+              exchange [cardinality: 165.56, doc-size: 70.0, op-cost: 0.0, total-cost: 1258620.94]
               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                assign [$$200] <- [get-year(date($$201))] project: [$$232, $$230, $$231, $$200] [cardinality: 160.49, doc-size: 70.0, op-cost: 0.0, total-cost: 1258616.83]
+                assign [$$200] <- [get-year(date($$201))] project: [$$232, $$230, $$231, $$200] [cardinality: 165.56, doc-size: 70.0, op-cost: 0.0, total-cost: 1258620.94]
                 -- ASSIGN  |PARTITIONED|
-                  project ([$$230, $$231, $$201, $$232]) [cardinality: 160.49, doc-size: 70.0, op-cost: 0.0, total-cost: 1258616.83]
+                  project ([$$230, $$231, $$201, $$232]) [cardinality: 165.56, doc-size: 70.0, op-cost: 0.0, total-cost: 1258620.94]
                   -- STREAM_PROJECT  |PARTITIONED|
-                    exchange [cardinality: 160.49, doc-size: 70.0, op-cost: 0.0, total-cost: 1258616.83]
+                    exchange [cardinality: 165.56, doc-size: 70.0, op-cost: 0.0, total-cost: 1258620.94]
                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                      join (eq($$216, $$209)) [cardinality: 160.49, doc-size: 70.0, op-cost: 262.6, total-cost: 1258616.83]
+                      join (eq($$216, $$209)) [cardinality: 165.56, doc-size: 70.0, op-cost: 265.56, total-cost: 1258620.94]
                       -- HYBRID_HASH_JOIN [$$216][$$209]  |PARTITIONED|
                         exchange [cardinality: 987.0, doc-size: 10.0, op-cost: 0.0, total-cost: 1000.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -52,11 +52,11 @@
                                         -- STREAM_PROJECT  |PARTITIONED|
                                           exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                           -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                            join (and(eq($$212, $$210), eq($$218, $$208))) [cardinality: 167.9, doc-size: 55.0, op-cost: 938.74, total-cost: 1256721.24]
+                                            join (and(eq($$212, $$210), eq($$218, $$208))) [cardinality: 167.74, doc-size: 55.0, op-cost: 938.68, total-cost: 1256720.76]
                                             -- HYBRID_HASH_JOIN [$$210, $$218][$$212, $$208]  |PARTITIONED|
                                               exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                assign [$$218] <- [$$c.getField(3)] project: [$$230, $$231, $$201, $$223, $$210, $$218] [cardinality: 838.74, doc-size: 45.0, op-cost: 4189.55, total-cost: 1255657.5]
+                                                assign [$$218] <- [$$c.getField(3)] project: [$$230, $$231, $$201, $$223, $$210, $$218] [cardinality: 838.68, doc-size: 45.0, op-cost: 4189.45, total-cost: 1255657.08]
                                                 -- ASSIGN  |PARTITIONED|
                                                   project ([$$230, $$231, $$223, $$210, $$201, $$c]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                   -- STREAM_PROJECT  |PARTITIONED|
@@ -70,7 +70,7 @@
                                                           -- STABLE_SORT [$$226(ASC)]  |PARTITIONED|
                                                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                             -- HASH_PARTITION_EXCHANGE [$$226]  |PARTITIONED|
-                                                              select (and(ge($$201, "1995-01-01"), le($$201, "1996-12-31"))) [cardinality: 837.9, doc-size: 35.0, op-cost: 14137.91, total-cost: 1248116.35]
+                                                              select (and(ge($$201, "1995-01-01"), le($$201, "1996-12-31"))) [cardinality: 837.89, doc-size: 35.0, op-cost: 14137.75, total-cost: 1248116.06]
                                                               -- STREAM_SELECT  |PARTITIONED|
                                                                 assign [$$226, $$201] <- [$$o.getField(1), $$o.getField(4)] project: [$$230, $$231, $$223, $$210, $$226, $$201] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                 -- ASSIGN  |PARTITIONED|
@@ -90,7 +90,7 @@
                                                                               -- STREAM_PROJECT  |PARTITIONED|
                                                                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                                                  join (eq($$202, $$221)) [cardinality: 2827.58, doc-size: 25.0, op-cost: 601513.27, total-cost: 1222668.12]
+                                                                                  join (eq($$202, $$221)) [cardinality: 2827.55, doc-size: 25.0, op-cost: 601513.27, total-cost: 1222668.12]
                                                                                   -- HYBRID_HASH_JOIN [$$221][$$202]  |PARTITIONED|
                                                                                     exchange [cardinality: 0.0, doc-size: 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/tpch/query-plans/query-plans.10.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.10.plan
index 2a1de5e..e7b9d0d 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.10.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.10.plan
@@ -1,22 +1,22 @@
-distribute result [$$122] [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+distribute result [$$122] [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+  exchange [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    assign [$$122] <- [{"$1": 9, "$2": $$140}] project: [$$122] [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+    assign [$$122] <- [{"$1": 9, "$2": $$140}] project: [$$122] [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
     -- ASSIGN  |UNPARTITIONED|
-      aggregate [$$140] <- [agg-sql-sum($$144)] [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+      aggregate [$$140] <- [agg-sql-sum($$144)] [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
       -- AGGREGATE  |UNPARTITIONED|
-        exchange [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+        exchange [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
         -- RANDOM_MERGE_EXCHANGE  |PARTITIONED|
-          aggregate [$$144] <- [agg-sql-count(1)] [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+          aggregate [$$144] <- [agg-sql-count(1)] [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
           -- AGGREGATE  |PARTITIONED|
-            exchange [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+            exchange [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              unnest-map [$$136, $$o] <- index-search("orders", 0, "Default", "tpch", "orders", true, true, 1, $$132, 1, $$132, true, true, true) [cardinality: 25648.6, doc-size: 50.0, op-cost: 0.0, total-cost: 1660495.02]
+              unnest-map [$$136, $$o] <- index-search("orders", 0, "Default", "tpch", "orders", true, true, 1, $$132, 1, $$132, true, true, true) [cardinality: 104.81, doc-size: 50.0, op-cost: 0.0, total-cost: 1421245.07]
               -- BTREE_SEARCH  |PARTITIONED|
                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                  order (ASC, $$132) [cardinality: 25648.6, doc-size: 50.0, op-cost: 128122.39, total-cost: 1660495.02]
+                  order (ASC, $$132) [cardinality: 104.81, doc-size: 50.0, op-cost: 523.57, total-cost: 1421245.07]
                   -- STABLE_SORT [$$132(ASC)]  |PARTITIONED|
                     exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                     -- HASH_PARTITION_EXCHANGE [$$132]  |PARTITIONED|
@@ -24,45 +24,57 @@
                       -- STREAM_PROJECT  |PARTITIONED|
                         exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          join (and(eq($$135, $$128), eq($$134, $$125))) [cardinality: 25624.47, doc-size: 45.0, op-cost: 614777.52, total-cost: 1429874.73]
-                          -- HYBRID_HASH_JOIN [$$128, $$125][$$135, $$134]  |PARTITIONED|
+                          join (eq($$138, $$137)) [cardinality: 104.71, doc-size: 45.0, op-cost: 129.71, total-cost: 1420302.63]
+                          -- HYBRID_HASH_JOIN [$$138][$$137]  |PARTITIONED|
                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              assign [$$128, $$125] <- [$$l.getField(2), $$l.getField(1)] project: [$$132, $$128, $$125] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                              -- ASSIGN  |PARTITIONED|
-                                project ([$$132, $$l]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                -- STREAM_PROJECT  |PARTITIONED|
-                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                    data-scan []<-[$$131, $$132, $$l] <- tpch.lineitem [cardinality: 600572.0, doc-size: 15.0, op-cost: 600572.0, total-cost: 600572.0]
-                                    -- DATASOURCE_SCAN  |PARTITIONED|
-                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                            -- BROADCAST_EXCHANGE  |PARTITIONED|
-                              project ([$$134, $$135]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- HASH_PARTITION_EXCHANGE [$$138]  |PARTITIONED|
+                              project ([$$138, $$132]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- STREAM_PROJECT  |PARTITIONED|
                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                  join (eq($$138, $$137)) [cardinality: 3410.13, doc-size: 30.0, op-cost: 3555.05, total-cost: 200884.68]
-                                  -- HYBRID_HASH_JOIN [$$138][$$137]  |PARTITIONED|
+                                  join (eq($$130, $$135)) [cardinality: 104.71, doc-size: 40.0, op-cost: 1411.38, total-cost: 1420018.2]
+                                  -- HYBRID_HASH_JOIN [$$130][$$135]  |PARTITIONED|
                                     exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      project ([$$134, $$135, $$138]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      assign [$$138] <- [$$s.getField(3)] project: [$$130, $$138] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- ASSIGN  |PARTITIONED|
+                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                          data-scan []<-[$$130, $$s] <- tpch.supplier [cardinality: 1000.0, doc-size: 10.0, op-cost: 1000.0, total-cost: 1000.0]
+                                          -- DATASOURCE_SCAN  |PARTITIONED|
+                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
+                                      project ([$$132, $$135]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                       -- STREAM_PROJECT  |PARTITIONED|
                                         exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          join (eq($$130, $$135)) [cardinality: 3455.05, doc-size: 25.0, op-cost: 4527.53, total-cost: 197204.63]
-                                          -- HYBRID_HASH_JOIN [$$135][$$130]  |PARTITIONED|
+                                          join (and(eq($$135, $$128), eq($$134, $$125))) [cardinality: 106.09, doc-size: 30.0, op-cost: 615298.92, total-cost: 1417182.45]
+                                          -- HYBRID_HASH_JOIN [$$128, $$125][$$135, $$134]  |PARTITIONED|
                                             exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                            -- HASH_PARTITION_EXCHANGE [$$135]  |PARTITIONED|
+                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                              assign [$$128, $$125] <- [$$l.getField(2), $$l.getField(1)] project: [$$132, $$128, $$125] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                              -- ASSIGN  |PARTITIONED|
+                                                project ([$$132, $$l]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                -- STREAM_PROJECT  |PARTITIONED|
+                                                  exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                  -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                    data-scan []<-[$$131, $$132, $$l] <- tpch.lineitem [cardinality: 600572.0, doc-size: 15.0, op-cost: 600572.0, total-cost: 600572.0]
+                                                    -- DATASOURCE_SCAN  |PARTITIONED|
+                                                      exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                      -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                                        empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                                        -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                            -- BROADCAST_EXCHANGE  |PARTITIONED|
                                               project ([$$134, $$135]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- STREAM_PROJECT  |PARTITIONED|
                                                 exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  join (eq($$129, $$134)) [cardinality: 3540.53, doc-size: 15.0, op-cost: 83612.42, total-cost: 187149.58]
+                                                  join (eq($$129, $$134)) [cardinality: 3540.49, doc-size: 15.0, op-cost: 83612.42, total-cost: 187149.58]
                                                   -- HYBRID_HASH_JOIN [$$134][$$129]  |PARTITIONED|
                                                     exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -88,27 +100,15 @@
                                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                                               empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              assign [$$138] <- [$$s.getField(3)] project: [$$130, $$138] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                              -- ASSIGN  |PARTITIONED|
-                                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                  data-scan []<-[$$130, $$s] <- tpch.supplier [cardinality: 1000.0, doc-size: 10.0, op-cost: 1000.0, total-cost: 1000.0]
-                                                  -- DATASOURCE_SCAN  |PARTITIONED|
-                                                    exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                              project ([$$137]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                              -- STREAM_PROJECT  |PARTITIONED|
+                                exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                  data-scan []<-[$$137, $$n] <- tpch.nation [cardinality: 25.0, doc-size: 5.0, op-cost: 25.0, total-cost: 25.0]
+                                  -- DATASOURCE_SCAN  |PARTITIONED|
                                     exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                    -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                      project ([$$137]) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                      -- STREAM_PROJECT  |PARTITIONED|
-                                        exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                        -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                          data-scan []<-[$$137, $$n] <- tpch.nation [cardinality: 25.0, doc-size: 5.0, op-cost: 25.0, total-cost: 25.0]
-                                          -- DATASOURCE_SCAN  |PARTITIONED|
-                                            exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                            -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                              empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
-                                              -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
+                                    -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
+                                      empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+                                      -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.11.plan b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.11.plan
index 9640ac0..b9130e8 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.11.plan
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results_cbo/tpch/query-plans/query-plans.11.plan
@@ -1,44 +1,44 @@
-distribute result [$$185] [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+distribute result [$$185] [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
 -- DISTRIBUTE_RESULT  |UNPARTITIONED|
-  exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+  exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
   -- ONE_TO_ONE_EXCHANGE  |UNPARTITIONED|
-    limit 20 [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+    limit 20 [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
     -- STREAM_LIMIT  |UNPARTITIONED|
-      assign [$$185] <- [{"$1": 10, "c_custkey": $$c_custkey, "c_name": $$c_name, "revenue": $$203, "c_acctbal": $$c_acctbal, "n_name": $$n_name, "c_address": $$c_address, "c_phone": $$c_phone, "c_comment": $$c_comment}] project: [$$185] [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+      assign [$$185] <- [{"$1": 10, "c_custkey": $$c_custkey, "c_name": $$c_name, "revenue": $$203, "c_acctbal": $$c_acctbal, "n_name": $$n_name, "c_address": $$c_address, "c_phone": $$c_phone, "c_comment": $$c_comment}] project: [$$185] [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
       -- ASSIGN  |PARTITIONED|
-        exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+        exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
         -- SORT_MERGE_EXCHANGE [$$203(DESC) ]  |PARTITIONED|
-          limit 20 [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+          limit 20 [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
           -- STREAM_LIMIT  |PARTITIONED|
-            exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+            exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-              order (topK: 20) (DESC, $$203) [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+              order (topK: 20) (DESC, $$203) [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
               -- STABLE_SORT [topK: 20] [$$203(DESC)]  |PARTITIONED|
-                exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+                exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                   group by ([$$c_custkey := $$211; $$c_name := $$212; $$c_acctbal := $$213; $$c_phone := $$214; $$n_name := $$215; $$c_address := $$216; $$c_comment := $$217]) decor ([]) {
                             aggregate [$$203] <- [global-sql-sum-serial($$210)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                             -- AGGREGATE  |LOCAL|
                               nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                               -- NESTED_TUPLE_SOURCE  |LOCAL|
-                         } [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 990469.45]
+                         } [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 990425.23]
                   -- EXTERNAL_GROUP_BY[$$211, $$212, $$213, $$214, $$215, $$216, $$217]  |PARTITIONED|
-                    exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 986028.73]
+                    exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 985988.93]
                     -- HASH_PARTITION_EXCHANGE [$$211, $$212, $$213, $$214, $$215, $$216, $$217]  |PARTITIONED|
                       group by ([$$211 := $$195; $$212 := $$187; $$213 := $$188; $$214 := $$189; $$215 := $$190; $$216 := $$191; $$217 := $$192]) decor ([]) {
                                 aggregate [$$210] <- [local-sql-sum-serial(numeric-multiply($$208, numeric-subtract(1, $$209)))] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                 -- AGGREGATE  |LOCAL|
                                   nested tuple source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                   -- NESTED_TUPLE_SOURCE  |LOCAL|
-                             } [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 986028.73]
+                             } [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 985988.93]
                       -- EXTERNAL_GROUP_BY[$$195, $$187, $$188, $$189, $$190, $$191, $$192]  |PARTITIONED|
-                        exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 981588.01]
+                        exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 981552.63]
                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                          project ([$$208, $$209, $$195, $$187, $$188, $$189, $$190, $$191, $$192]) [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 981588.01]
+                          project ([$$208, $$209, $$195, $$187, $$188, $$189, $$190, $$191, $$192]) [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 981552.63]
                           -- STREAM_PROJECT  |PARTITIONED|
-                            exchange [cardinality: 4440.72, doc-size: 30.0, op-cost: 0.0, total-cost: 981588.01]
+                            exchange [cardinality: 4436.3, doc-size: 30.0, op-cost: 0.0, total-cost: 981552.63]
                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                              join (eq($$198, $$196)) [cardinality: 4440.72, doc-size: 30.0, op-cost: 169510.74, total-cost: 981588.01]
+                              join (eq($$198, $$196)) [cardinality: 4436.3, doc-size: 30.0, op-cost: 169493.29, total-cost: 981552.63]
                               -- HYBRID_HASH_JOIN [$$198][$$196]  |PARTITIONED|
                                 exchange [cardinality: 151979.18, doc-size: 5.0, op-cost: 0.0, total-cost: 600572.0]
                                 -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
@@ -56,13 +56,13 @@
                                             -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
                                               empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
                                               -- EMPTY_TUPLE_SOURCE  |PARTITIONED|
-                                exchange [cardinality: 4382.89, doc-size: 25.0, op-cost: 0.0, total-cost: 193973.72]
+                                exchange [cardinality: 4378.53, doc-size: 25.0, op-cost: 0.0, total-cost: 193973.24]
                                 -- BROADCAST_EXCHANGE  |PARTITIONED|
-                                  project ([$$195, $$187, $$188, $$189, $$190, $$191, $$192, $$196]) [cardinality: 4382.89, doc-size: 25.0, op-cost: 0.0, total-cost: 193973.72]
+                                  project ([$$195, $$187, $$188, $$189, $$190, $$191, $$192, $$196]) [cardinality: 4378.53, doc-size: 25.0, op-cost: 0.0, total-cost: 193973.24]
                                   -- STREAM_PROJECT  |PARTITIONED|
-                                    exchange [cardinality: 4382.89, doc-size: 25.0, op-cost: 0.0, total-cost: 193973.72]
+                                    exchange [cardinality: 4378.53, doc-size: 25.0, op-cost: 0.0, total-cost: 193973.24]
                                     -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
-                                      join (eq($$201, $$199)) [cardinality: 4382.89, doc-size: 25.0, op-cost: 4478.77, total-cost: 193973.72]
+                                      join (eq($$201, $$199)) [cardinality: 4378.53, doc-size: 25.0, op-cost: 4478.53, total-cost: 193973.24]
                                       -- HYBRID_HASH_JOIN [$$201][$$199]  |PARTITIONED|
                                         exchange [cardinality: 15014.11, doc-size: 10.0, op-cost: 0.0, total-cost: 15000.0]
                                         -- ONE_TO_ONE_EXCHANGE  |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
index 10e8302..a472904 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/sqlpp_queries.xml
@@ -15922,7 +15922,7 @@
         <expected-warn><![CDATA[ASX1132: Invalid specification for hint productivity. Invalid format for productivity values (in line 31, at column 23)]]></expected-warn>
         <expected-warn><![CDATA[ASX1132: Invalid specification for hint productivity. Invalid format for productivity values (in line 31, at column 23)]]></expected-warn>
         <expected-warn><![CDATA[ASX1132: Invalid specification for hint productivity. Invalid format for productivity values (in line 31, at column 23)]]></expected-warn>
-        <expected-warn>HYR10006: Could not apply productivity hint: Productivity specified: 0.0, has to be a decimal value greater than 0 (in line 33, at column 47)</expected-warn>
+        <expected-warn><![CDATA[ASX1132: Invalid specification for hint productivity. Productivity has to be a decimal value greater than 0 (in line 33, at column 23)]]></expected-warn>
       </compilation-unit>
     </test-case>
     <test-case FilePath="warnings" check-warnings="true">
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 7a46e95..a91b3d5 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -774,6 +774,9 @@
                  Matcher numMat = number.matcher(matchedGroup);
                  if (numMat.find()) {
                    productivity = Double.parseDouble (numMat.group());
+                   if (productivity == 0.0) {
+                     throw new SqlppParseException(getSourceLocation(hintToken), "Productivity has to be a decimal value greater than 0");
+                   }
                  }
                  else {
                    throw new SqlppParseException(getSourceLocation(hintToken), "Productivity has to be a decimal value greater than 0");