>From Preetham Poluparthi <[email protected]>:

Preetham Poluparthi has uploaded this change for review. ( 
https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21388?usp=email )


Change subject: WIP: Improve cbo cost functions
......................................................................

WIP: Improve cbo cost functions

Change-Id: I2d131cd430775a0e7dbf10e7491f0fa2e0f5ed3c
---
A 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCost.java
A 
asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCostMethods.java
2 files changed, 601 insertions(+), 0 deletions(-)



  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/88/21388/1

diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCost.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCost.java
new file mode 100644
index 0000000..858b71d
--- /dev/null
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCost.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2016-2022 Couchbase, Inc.
+ */
+
+package org.apache.asterix.optimizer.cost;
+
+public class CBCost extends Cost {
+
+    private static final int SEQ_IO_WEIGHT = 1;
+    private static final int RAND_IO_WEIGHT = 0;
+    // not using random costs any more because index access happens after 
sorts. May consider removing this component in V2
+
+    private final double docsProcessed;
+    private final double docsProduced;
+    private final double docsSent;
+    private final double overFlow;
+    private final double ioSeq;
+    private final double ioRand;
+
+    public CBCost() {
+        this(0, 0, 0, 0, 0, 0);
+    }
+
+    public CBCost(double docsProcessed, double docsProduced, double docsSent, 
double overFlow, double ioSeq,
+            double ioRand) {
+        this.docsProcessed = docsProcessed;
+        this.docsProduced = docsProduced;
+        this.docsSent = docsSent;
+        this.overFlow = overFlow;
+        this.ioSeq = ioSeq;
+        this.ioRand = ioRand;
+    }
+
+    @Override
+    public ICost zeroCost() {
+        return new CBCost();
+    }
+
+    @Override
+    public ICost maxCost() {
+        return new CBCost(MAX_CARD, MAX_CARD, MAX_CARD, MAX_CARD, 0, 0);
+    }
+
+    @Override
+    public ICost costAdd(ICost cost) {
+        CBCost cbCost = (CBCost) cost;
+        return new CBCost(docsProcessed + cbCost.docsProcessed, docsProduced + 
cbCost.docsProduced,
+                docsSent + cbCost.docsSent, overFlow + cbCost.overFlow, ioSeq 
+ cbCost.ioSeq, ioRand + cbCost.ioRand);
+    }
+
+    @Override
+    public double computeTotalCost() {
+        return docsProcessed + docsProduced + docsSent + overFlow + ioSeq * 
SEQ_IO_WEIGHT + ioRand * RAND_IO_WEIGHT;
+    }
+
+    public double getDocsProcessed() {
+        return docsProcessed;
+    }
+
+    public double getDocsProduced() {
+        return docsProduced;
+    }
+
+    public double getDocsSent() {
+        return docsSent;
+    }
+
+    public double getOverFlow() {
+        return overFlow;
+    }
+
+    public double getIoSeq() {
+        return ioSeq;
+    }
+
+    public double getIoRand() {
+        return ioRand;
+    }
+
+    @Override
+    public String toString() {
+        return "{docsProcessed = " + docsProcessed + ", docsProduced = " + 
docsProduced + ", docsSent = " + docsSent
+                + ", overFlow = " + overFlow + ", ioSeq = " + ioSeq + ", 
ioRand = " + ioRand + '}';
+    }
+}
diff --git 
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCostMethods.java
 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCostMethods.java
new file mode 100644
index 0000000..192f106
--- /dev/null
+++ 
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/cost/CBCostMethods.java
@@ -0,0 +1,516 @@
+/*
+ * Copyright 2016-2022 Couchbase, Inc.
+ */
+
+package org.apache.asterix.optimizer.cost;
+
+import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.optimizer.rules.cbo.AbstractPlanNode;
+import org.apache.asterix.optimizer.rules.cbo.JoinNode;
+import org.apache.asterix.optimizer.rules.cbo.JoinPlanNode;
+import org.apache.asterix.optimizer.rules.cbo.ScanPlanNode;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.DistinctOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.GroupByOperator;
+import 
org.apache.hyracks.algebricks.core.algebra.operators.logical.OrderOperator;
+
+public class CBCostMethods extends CostMethods {
+
+    public CBCostMethods(IOptimizationContext context) {
+        super(context);
+    }
+
+    @Override
+    public CBCost costFullScan(JoinNode jn) {
+        int limit = jn.getLimitVal();
+        double factor = 1.0;
+        double inputCard = jn.getOrigCardinality();
+        double outputCard = jn.getCardinality();
+        double documentSize = jn.getAvgDocSize(); //the entire row will come 
out
+        double inputSize = jn.getInputSize(); // This is the size coming out 
of the disk
+        if (!jn.getColumnar()) {
+            inputSize = documentSize;
+        }
+        double outputSize = jn.getOutputSize(); // this is what leaves after 
the scan; only join and result vars are included here
+
+        if (limit > 0 && limit < outputCard) { // for single tables only
+            factor = limit / outputCard;
+            outputCard = limit;
+        }
+        double docsProcessed = factor * inputCard / DOP * 
docSizeFactor(inputSize);
+        double docsProduced = outputCard / DOP * docSizeFactor(outputSize);
+
+        // Since we do not have exchanges at the logical plan level, docsSent 
for the exchange above the
+        // scan will be computed by the logical operator above the scan which 
will determine the properties
+        // of the exchange operator above the scan in the final physical plan.
+        double docsSent = 0;
+        double ioSeq = factor * inputCard / DOP * inputSize / blockSize;
+        double ioRand = 0;
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, 0, ioSeq, 
ioRand);
+    }
+
+    @Override
+    public CBCost costIndexScan(JoinNode jn, double indexSel) {
+        int limit = jn.getLimitVal();
+        double inputCard = jn.getOrigCardinality();
+        double outputCard = jn.getCardinality();
+        double inputSize = jn.getInputSize(); // original size of the dataset
+        double outputSize = jn.getOutputSize();
+
+        if (limit > 0 && limit < outputCard) {
+            indexSel = limit / inputCard;
+        }
+
+        double docsProcessed = inputCard * indexSel / DOP * 
docSizeFactor(outputSize);
+        double docsProduced = inputCard * indexSel / DOP * 
docSizeFactor(outputSize);
+        double docsSent = 0;
+        //double ioSeq = outputCard / DOP * outputSize / blockSize;
+        double ioSeq = inputCard * indexSel / DOP * outputSize / blockSize;
+        double ioRand = 0;
+        return new CBCost(docsProcessed, docsProduced, docsSent, 0, ioSeq, 
ioRand);
+    }
+
+    public CBCost costIndexDataScan(JoinNode jn, double indexSel) {
+        int limit = jn.getLimitVal(); // stored earlier
+        double inputCard = jn.getOrigCardinality();
+        double outputCard = jn.getCardinality();
+        double inputSize = jn.getInputSize(); // original size of the dataset
+        double outputSize = jn.getOutputSize();
+
+        if (limit > 0 && limit < outputCard) {
+            indexSel = limit / inputCard;
+        }
+
+        // Duplicates RIDs will be removed by the distinct operator in case of 
array indexes.
+        // We account for that with the unnestFactor, which is 1.0 for regular 
indexes.
+        double docsProcessed = inputCard * indexSel / DOP / 
jn.getUnnestFactor() * docSizeFactor(outputSize);
+        double docsProduced = inputCard * indexSel / DOP * 
docSizeFactor(outputSize);
+        double docsSent = 0;
+
+        // Since we do not have exchanges at the logical plan level, docsSent 
for the exchange above the
+        // scan will be computed by the logical operator above the scan which 
will determine the properties
+        // of the exchange operator above the scan in the final physical plan.
+        double ioSeq = 0;
+        double ioRand = 0;
+
+        // Need to sort the RIDs before the data access. This happens in the 
sort operator
+        // between the index scan and the data scan operator, so we cost it 
here.
+        docsProcessed += costSort(docsProcessed, inputSize);
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, 0, ioSeq, 
ioRand);
+    }
+
+    @Override
+    public CBCost costHashJoin(JoinNode jn) {
+        JoinNode leftJn = jn.getLeftJn();
+        JoinNode rightJn = jn.getRightJn();
+
+        double probeCard = leftJn.getCardinality();
+        double probeSize = leftJn.getOutputSize();
+        double buildCard = rightJn.getCardinality();
+        double buildSize = rightJn.getOutputSize();
+        double joinCard = jn.getCardinality();
+        double joinSize = jn.getOutputSize();
+
+        double probeCardPerPartition = probeCard / DOP;
+        double buildCardPerPartition = buildCard / DOP;
+        double joinCardPerPartition = joinCard / DOP;
+
+        double probeSizeFactor = docSizeFactor(probeSize);
+        double buildSizeFactor = docSizeFactor(buildSize);
+        double joinSizeFactor = docSizeFactor(joinSize);
+
+        // Regular (not broadcast) hash join.
+        double docsProcessed = probeCardPerPartition * probeSizeFactor + 
buildCardPerPartition * buildSizeFactor;
+
+        double overFlowCost =
+                computeHashJoinOverflowCost(probeCardPerPartition, probeSize, 
buildCardPerPartition, buildSize);
+
+        double docsProduced = joinCardPerPartition * joinSizeFactor;
+
+        // Since we do not have exchanges at the logical plan level, docsSent 
for the exchange above the
+        // join will be computed by the logical operator above the join which 
will determine the properties
+        // of the exchange operator above the join in the final physical plan.
+        double docsSent = 0;
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, overFlowCost, 
0, 0);
+    }
+
+    // This will be used later in the final physical plan to assign costs to 
the exchange and
+    // subtract it from the cost assigned to the hash join.
+    @Override
+    public CBCost computeHJProbeExchangeCost(JoinNode jn) {
+        JoinNode leftJn = jn.getLeftJn();
+        double probeCard = leftJn.getCardinality();
+        double probeSize = leftJn.getOutputSize();
+        double probeCardPerPartition = probeCard / DOP;
+        double probeSizeFactor = docSizeFactor(probeSize);
+        boolean probePartitioned = false;
+        double docsSent = 0;
+        if (!probePartitioned) {
+            docsSent += probeCardPerPartition * probeSizeFactor;
+        }
+        return new CBCost(0, 0, docsSent, 0, 0, 0);
+    }
+
+    // This will be used later in the final physical plan to assign costs to 
the exchange and
+    // subtract it from the cost assigned to the hash join.
+    @Override
+    public CBCost computeHJBuildExchangeCost(JoinNode jn) {
+        JoinNode rightJn = jn.getRightJn();
+        double buildCard = rightJn.getCardinality();
+        double buildSize = rightJn.getOutputSize();
+        double buildCardPerPartition = buildCard / DOP;
+        double buildSizeFactor = docSizeFactor(buildSize);
+        boolean buildPartitioned = false;
+        double docsSent = 0;
+        if (!buildPartitioned) {
+            docsSent += buildCardPerPartition * buildSizeFactor;
+        }
+        return new CBCost(0, 0, docsSent, 0, 0, 0);
+    }
+
+    @Override
+    public CBCost costBroadcastHashJoin(JoinNode jn) {
+        JoinNode leftJn = jn.getLeftJn();
+        JoinNode rightJn = jn.getRightJn();
+
+        double probeCard = leftJn.getCardinality();
+        double probeSize = leftJn.getOutputSize();
+        double buildCard = rightJn.getCardinality();
+        double buildSize = rightJn.getOutputSize();
+        double joinCard = jn.getCardinality();
+        double joinSize = jn.getOutputSize();
+
+        double probeCardPerPartition = probeCard / DOP;
+        double buildCardPerPartition = buildCard; // The build side is 
broadcast
+        double joinCardPerPartition = joinCard / DOP;
+
+        double probeSizeFactor = docSizeFactor(probeSize);
+        double buildSizeFactor = docSizeFactor(buildSize);
+        double joinSizeFactor = docSizeFactor(joinSize);
+
+        // Broadcast hash join.
+        double docsProcessed = probeCardPerPartition * probeSizeFactor + 
buildCardPerPartition * buildSizeFactor;
+        double overFlowCost =
+                computeHashJoinOverflowCost(probeCardPerPartition, probeSize, 
buildCardPerPartition, buildSize);
+
+        double docsProduced = joinCardPerPartition * joinSizeFactor;
+        // Since we do not have exchanges at the logical plan level, docsSent 
for the exchange above the
+        // join will be computed by the logical operator above the join which 
will determine the properties
+        // of the exchange operator above the join in the final physical plan.
+        double docsSent = 0;
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, overFlowCost, 
0, 0);
+    }
+
+    // This will be used later in the final physical plan to assign costs to 
the exchange and
+    // subtract it from the cost assigned to the broadcast hash join.
+    @Override
+    public CBCost computeBHJBuildExchangeCost(JoinNode jn) {
+        JoinNode rightJn = jn.getRightJn();
+        double buildCard = rightJn.getCardinality();
+        double buildSize = rightJn.getOutputSize();
+        double buildCardPerPartition = buildCard;
+        double buildSizeFactor = docSizeFactor(buildSize);
+        double docsSent = buildCardPerPartition * buildSizeFactor;
+        return new CBCost(0, 0, docsSent, 0, 0, 0);
+    }
+
+    // This routine is the weakest. May need to revisit this multiple times.
+    @Override
+    public CBCost costIndexNLJoin(JoinNode jn, Index index) {
+        JoinNode leftJn = jn.getLeftJn();
+        JoinNode rightJn = jn.getRightJn();
+
+        double outerCard = leftJn.getCardinality();
+        double outerSize = leftJn.getOutputSize();
+        double innerCard = rightJn.getCardinality();
+        double innerSize = rightJn.getOutputSize();
+        double joinCard = jn.getCardinality();
+        double joinSize = jn.getOutputSize();
+
+        double outerCardPerPartition = outerCard; // outer side is broadcast 
to all nodes
+        double innerCardPerPartition = innerCard / DOP;
+        double joinCardPerPartition = joinCard / DOP;
+
+        double outerSizeFactor = docSizeFactor(outerSize);
+        double innerSizeFactor = docSizeFactor(innerSize);
+        double joinSizeFactor = docSizeFactor(joinSize);
+
+        double origRightCard = rightJn.getOrigCardinality();
+        double tuplesTobeSortedPerInstance = joinCardPerPartition * 
origRightCard / innerCard;
+        // innerCard/origRightCard is the selectivity for the right side.
+
+        // The probes from the outer side are processed by the nested join
+        // and sent down to the inner side. The result join tuples flow back
+        // up to the nested join.
+
+        double docsProcessed = outerCardPerPartition * outerSizeFactor;
+
+        double docsProduced = joinCardPerPartition * joinSizeFactor;
+
+        // Since we do not have exchanges at the logical plan level, docsSent 
for the exchange above the
+        // join will be computed by the logical operator above the join which 
will determine the properties
+        // of the exchange operator above the join in the final physical plan.
+        double docsSent = 0;
+        double ioSeq = joinCardPerPartition * innerSize / blockSize;
+        if (!index.isPrimaryIndex()) {
+            docsProcessed += costSort(tuplesTobeSortedPerInstance, joinSize);
+            docsProcessed += 5 * outerCardPerPartition * outerSizeFactor; // 
empirical evidence
+        }
+        // we will assume that the outerCard is always sorted.
+        // This need not be the same if the outercard is already sorted. But 
hard to tell this at the LO level.
+        if (outerCard > 1 && outerSideIsNotSorted(jn)) {
+            docsProcessed += costSort(4 * outerCard, outerSize); // had to 
increase this cost by 4x from empirical evidence
+        }
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, 0, ioSeq, 0);
+    }
+
+    private boolean outerSideIsNotSorted(JoinNode jn) {
+
+        JoinNode leftJn = jn.getLeftJn();
+        AbstractPlanNode pn = leftJn.getCheapestPlanNode();
+        if (pn instanceof JoinPlanNode) {
+            return true; // we cant tell here if the outer side is sorted or 
not.
+        }
+        Index index = ((ScanPlanNode) pn).getSoleAccessIndex();
+
+        if (index == null) {
+            return true;
+        }
+
+        if (index.isPrimaryIndex()) {
+            return false;
+        }
+
+        return true;
+    }
+
+    // This will be used later in the final physical plan to assign costs to 
the exchange and
+    // subtract it from the cost assigned to the index NL join.
+    @Override
+    public CBCost computeNLJOuterExchangeCost(JoinNode jn) {
+        JoinNode leftJn = jn.getLeftJn();
+        double outerCard = leftJn.getCardinality();
+        double outerSize = leftJn.getOutputSize();
+        double outerCardPerPartition = outerCard;
+        double outerSizeFactor = docSizeFactor(outerSize);
+        double docsSent = outerCardPerPartition * outerSizeFactor;
+        return new CBCost(0, 0, docsSent, 0, 0, 0);
+    }
+
+    @Override
+    public CBCost costCartesianProductJoin(JoinNode jn) {
+        JoinNode leftJn = jn.getLeftJn();
+        JoinNode rightJn = jn.getRightJn();
+
+        double leftCard = leftJn.getCardinality();
+        double leftSize = leftJn.getOutputSize();
+        double rightCard = rightJn.getCardinality();
+        double rightSize = rightJn.getOutputSize();
+        double joinCard = jn.getCardinality();
+        double joinSize = jn.getOutputSize();
+
+        double leftCardPerPartition = leftCard / DOP;
+        double rightCardPerPartition = rightCard; // the right side is 
broadcast
+        double joinCardPerPartition = joinCard / DOP;
+
+        double leftSizeFactor = docSizeFactor(leftSize);
+        double rightSizeFactor = docSizeFactor(rightSize);
+        double joinSizeFactor = docSizeFactor(joinSize);
+
+        double docsProcessed = Math.max(leftCardPerPartition, Cost.MIN_CARD) * 
leftSizeFactor
+                * Math.max(rightCardPerPartition, Cost.MIN_CARD) * 
rightSizeFactor;
+        double docsProduced = joinCardPerPartition * joinSizeFactor;
+        // Since we do not have exchanges at the logical plan level, docsSent 
for the exchange above the
+        // join will be computed by the logical operator above the join which 
will determine the properties
+        // of the exchange operator above the join in the final physical plan.
+        double docsSent = 0;
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, 0, 0, 0);
+    }
+
+    // This will be used later in the final physical plan to assign costs to 
the exchange and
+    // subtract it from the cost assigned to the cartesian product join.
+    @Override
+    public CBCost computeCPRightExchangeCost(JoinNode jn) {
+        return computeBHJBuildExchangeCost(jn);
+    }
+
+    public CBCost costHashGroupBy(GroupByOperator groupByOperator) {
+        double inputCard, inputCardPerPartition;
+        double outputCard, outputCardPerPartition;
+        double inputSize = 1.0; // for now
+        double outputSize = 1.0; // for now
+
+        Pair<Double, Double> cards = getOpCards(groupByOperator);
+        inputCard = cards.getFirst();
+        outputCard = cards.getSecond();
+
+        if (groupByOperator.isGlobal()) {
+            inputCardPerPartition = outputCard * DOP;
+        } else {
+            inputCardPerPartition = inputCard / DOP;
+        }
+        outputCardPerPartition = outputCard;
+
+        double docsProcessed = inputCardPerPartition * 
docSizeFactor(inputSize);
+        double docsProduced = outputCardPerPartition * 
docSizeFactor(outputSize);
+        double docsSent = 0.0;
+        double overFlowCost =
+                computeHashGroupByOverflowCost(inputCardPerPartition, 
inputSize, outputCardPerPartition, outputSize);
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, overFlowCost, 
0, 0);
+    }
+
+    public CBCost costSortGroupBy(GroupByOperator groupByOperator) {
+        double inputCard, inputCardPerPartition;
+        double outputCard, outputCardPerPartition;
+        double inputSize = 1.0; // for now
+        double outputSize = 1.0; // for now
+
+        Pair<Double, Double> cards = getOpCards(groupByOperator);
+        inputCard = cards.getFirst();
+        outputCard = cards.getSecond();
+
+        if (groupByOperator.isGlobal()) {
+            inputCardPerPartition = outputCard * DOP;
+        } else {
+            inputCardPerPartition = inputCard / DOP;
+        }
+        outputCardPerPartition = outputCard;
+
+        double docsProcessed = inputCardPerPartition * 
docSizeFactor(inputSize);
+        docsProcessed += costSort(inputCardPerPartition, inputSize);
+        double docsProduced = outputCardPerPartition * 
docSizeFactor(outputSize);
+        double docsSent = 0.0;
+        double overFlowCost = computeSortOverflowCost(inputCardPerPartition, 
inputSize);
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, overFlowCost, 
0, 0);
+    }
+
+    public CBCost costDistinct(DistinctOperator distinctOp) {
+        double inputCard, inputCardPerPartition;
+        double outputCard, outputCardPerPartition;
+        double inputSize = 1.0; // for now
+        double outputSize = 1.0; // for now
+
+        Pair<Double, Double> cards = getOpCards(distinctOp);
+        inputCard = cards.getFirst();
+        outputCard = cards.getSecond();
+
+        inputCardPerPartition = inputCard / DOP;
+        outputCardPerPartition = outputCard / DOP;
+
+        double docsProcessed = inputCardPerPartition * 
docSizeFactor(inputSize);
+        docsProcessed += costSort(inputCardPerPartition, inputSize);
+        double docsProduced = outputCardPerPartition * 
docSizeFactor(outputSize);
+        double docsSent = 0.0;
+        double overFlowCost = computeSortOverflowCost(inputCardPerPartition, 
inputSize);
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, overFlowCost, 
0, 0);
+    }
+
+    public CBCost costOrderBy(OrderOperator orderOp) {
+        double inputCard, inputCardPerPartition;
+        double outputCard, outputCardPerPartition;
+        double inputSize = 1.0; // for now
+        double outputSize = 1.0; // for now
+
+        Pair<Double, Double> cards = getOpCards(orderOp);
+        inputCard = cards.getFirst();
+        outputCard = cards.getSecond();
+
+        inputCardPerPartition = inputCard / DOP;
+        outputCardPerPartition = outputCard / DOP;
+
+        double docsProcessed = inputCardPerPartition * 
docSizeFactor(inputSize);
+        docsProcessed += costSort(inputCardPerPartition, inputSize);
+        double docsProduced = outputCardPerPartition * 
docSizeFactor(outputSize);
+        double docsSent = 0.0;
+        double overFlowCost = computeSortOverflowCost(inputCardPerPartition, 
inputSize);
+
+        return new CBCost(docsProcessed, docsProduced, docsSent, overFlowCost, 
0, 0);
+    }
+
+    private double docSizeFactor(double size) {
+        return 1.0;
+        //return Math.sqrt(size);
+    }
+
+    private double computeHashJoinOverflowCost(double probeCard, double 
probeSize, double buildCard, double buildSize) {
+        double memoryUsed = buildCard * buildSize;
+        double probeSizeFactor = docSizeFactor(probeSize);
+        double buildSizeFactor = docSizeFactor(buildSize);
+
+        if (memoryUsed <= maxMemorySizeForJoin) {
+            return 0;
+        }
+
+        // memoryUsed > maxMemorySize
+        double fractionOverflow = 1.0 - maxMemorySizeForJoin / memoryUsed;
+
+        // The factor of 2 comes from having to write overflow tuples to disk 
and
+        // read back the overflow tuples from disk.
+        double buildOverFlow = 2.0 * fractionOverflow * buildCard * 
buildSizeFactor;
+
+        // The factor of 2 comes from having to write overflow tuples to disk 
and
+        // read back the overflow tuples from disk.
+        double probeOverFlow = 2.0 * fractionOverflow * probeCard * 
probeSizeFactor;
+
+        return (buildOverFlow + probeOverFlow);
+    }
+
+    private double computeHashGroupByOverflowCost(double inputCard, double 
inputSize, double outputCard,
+            double outputSize) {
+        double memoryUsed = outputCard * outputSize;
+        double inputSizeFactor = docSizeFactor(inputSize);
+
+        if (memoryUsed <= maxMemorySizeForGroup) {
+            return 0;
+        }
+
+        // memoryUsed > maxMemorySize
+        double fractionOverflow = 1.0 - maxMemorySizeForGroup / memoryUsed;
+
+        // The factor of 2 comes from having to write overflow tuples to disk 
and
+        // read back the overflow tuples from disk.
+        double overFlow = 2.0 * fractionOverflow * inputCard * inputSizeFactor;
+
+        return overFlow;
+    }
+
+    private double computeSortOverflowCost(double inputCard, double inputSize) 
{
+        double memoryUsed = inputCard * inputSize;
+        double inputSizeFactor = docSizeFactor(inputSize);
+
+        if (memoryUsed <= maxMemorySizeForSort) {
+            return 0;
+        }
+
+        // memoryUsed > maxMemorySize
+        double fractionOverflow = 1.0 - maxMemorySizeForSort / memoryUsed;
+
+        // The factor of 2 comes from having to write overflow tuples to disk 
and
+        // read back the overflow tuples from disk.
+        double overFlow = 2.0 * fractionOverflow * inputCard * inputSizeFactor;
+
+        return overFlow;
+    }
+
+    public double costSort(double inputCard, double inputSize) {
+        double docsProcessed = 0;
+        if (inputCard > 1) {
+            docsProcessed = inputCard * Math.log(inputCard) / Math.log(2); // 
log to the base 2
+            // want to avoid -ve costs as log can return -ve values.
+            docsProcessed = Math.max(docsProcessed, 0);
+        }
+        docsProcessed *= docSizeFactor(inputSize);
+
+        return docsProcessed;
+    }
+}

--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21388?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://asterix-gerrit.ics.uci.edu/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: I2d131cd430775a0e7dbf10e7491f0fa2e0f5ed3c
Gerrit-Change-Number: 21388
Gerrit-PatchSet: 1
Gerrit-Owner: Preetham Poluparthi <[email protected]>

Reply via email to