[ASTERIXDB-3399][COMP] Adding support for Primary index nested loop joins
Change-Id: I832db938f9bb704b13a0dd76d71d2c3edb12adf1
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18290
Reviewed-by: Vijay Sarathy <vijay.sarathy@couchbase.com>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
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 0ff630d..d5743e4 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
@@ -87,6 +87,7 @@
protected List<String> datasetNames;
protected List<String> aliases;
protected int cheapestPlanIndex;
+ protected PlanNode cheapestPlanNode;
private ICost cheapestPlanCost;
protected double origCardinality; // without any selections
protected double cardinality;
@@ -119,6 +120,7 @@
this.jnArrayIndex = i;
planIndexesArray = new ArrayList<>();
cheapestPlanIndex = PlanNode.NO_PLAN;
+ cheapestPlanNode = null;
size = 1; // for now, will be the size of the doc for this joinNode
}
@@ -149,6 +151,10 @@
return origCardinality;
}
+ public PlanNode getCheapestPlanNode() {
+ return cheapestPlanNode;
+ }
+
protected void setOrigCardinality(double card, boolean setMinCard) {
// Minimum cardinality for operators is MIN_CARD to prevent bad plans due to cardinality under estimation errors.
origCardinality = setMinCard ? Math.max(card, Cost.MIN_CARD) : card;
@@ -707,7 +713,7 @@
boolean forceEnum = mandatoryIndexesInfo.size() > 0 || level <= joinEnum.cboFullEnumLevel;
if (opCost.costLT(this.cheapestPlanCost) || forceEnum) {
pn = new PlanNode(allPlans.size(), joinEnum, this, datasetNames.get(0), leafInput);
- pn.setScanAndHintInfo(PlanNode.ScanMethod.INDEX_SCAN, mandatoryIndexesInfo);
+ pn.setScanAndHintInfo(PlanNode.ScanMethod.INDEX_SCAN, mandatoryIndexesInfo, optionalIndexesInfo);
pn.setScanCosts(totalCost);
planIndexesArray.add(pn.allPlansIndex);
allPlans.add(pn);
@@ -1443,6 +1449,7 @@
PlanNode cheapestPlan = forceEnum ? findCheapestPlan() : pn;
cheapestPlanCost = cheapestPlan.totalCost;
cheapestPlanIndex = cheapestPlan.allPlansIndex;
+ cheapestPlanNode = cheapestPlan;
}
@Override
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java
index e51990e..2cf9130 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/PlanNode.java
@@ -49,6 +49,7 @@
protected ScanMethod scanOp;
protected boolean indexHint;
+ Index indexUsed;
protected JoinMethod joinOp;
@@ -81,6 +82,10 @@
return allPlansIndex;
}
+ public Index getSoleAccessIndex() {
+ return indexUsed;
+ }
+
private int[] getPlanIndexes() {
return planIndexes;
}
@@ -143,7 +148,7 @@
return getLeftPlanIndex() == NO_PLAN && getRightPlanIndex() == NO_PLAN;
}
- protected boolean IsJoinNode() {
+ public boolean IsJoinNode() {
return getLeftPlanIndex() != NO_PLAN && getRightPlanIndex() != NO_PLAN;
}
@@ -231,6 +236,7 @@
jn = null;
planIndexes = new int[2]; // 0 is for left, 1 is for right
jnIndexes = new int[2]; // join node index(es)
+ indexUsed = null;
setLeftJoinIndex(JoinNode.NO_JN);
setRightJoinIndex(JoinNode.NO_JN);
setLeftPlanIndex(PlanNode.NO_PLAN);
@@ -251,6 +257,7 @@
this.leafInput = leafInput;
planIndexes = new int[2]; // 0 is for left, 1 is for right
jnIndexes = new int[2]; // join node index(es)
+ indexUsed = null;
setLeftJoinIndex(jn.jnArrayIndex);
setRightJoinIndex(JoinNode.NO_JN);
setLeftPlanIndex(PlanNode.NO_PLAN); // There ane no plans below this plan.
@@ -269,6 +276,7 @@
this.outerJoin = outerJoin;
planIndexes = new int[2]; // 0 is for left, 1 is for right
jnIndexes = new int[2]; // join node index(es)
+ indexUsed = null; // used for NL costing
setLeftJoinIndex(leftPlan.jn.jnArrayIndex);
setRightJoinIndex(rightPlan.jn.jnArrayIndex);
setLeftPlanIndex(leftPlan.allPlansIndex);
@@ -279,12 +287,22 @@
}
protected void setScanAndHintInfo(ScanMethod scanMethod,
- List<Triple<Index, Double, AbstractFunctionCallExpression>> mandatoryIndexesInfo) {
+ List<Triple<Index, Double, AbstractFunctionCallExpression>> mandatoryIndexesInfo,
+ List<Triple<Index, Double, AbstractFunctionCallExpression>> optionalIndexesInfo) {
setScanMethod(scanMethod);
if (mandatoryIndexesInfo.size() > 0) {
indexHint = true;
numHintsUsed = 1;
}
+ // keeping things simple. When multiple indexes are used, we cannot be sure of the order.
+ // So seeing if only index is used.
+ if (optionalIndexesInfo.size() + mandatoryIndexesInfo.size() == 1) {
+ if (optionalIndexesInfo.size() == 1) {
+ indexUsed = optionalIndexesInfo.get(0).first;
+ } else {
+ indexUsed = mandatoryIndexesInfo.get(0).first;
+ }
+ }
}
protected void setScanCosts(ICost opCost) {