This is an automated email from the ASF dual-hosted git repository.
mblow pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/asterixdb.git
The following commit(s) were added to refs/heads/master by this push:
new 29f1d423b7 [ASTERIXDB-3377][COMP]: CBO choosing wrong index
29f1d423b7 is described below
commit 29f1d423b7a8ebff0abc7ff40534463a66b1a33b
Author: Vijay Sarathy <[email protected]>
AuthorDate: Mon Apr 15 15:07:08 2024 -0700
[ASTERIXDB-3377][COMP]: CBO choosing wrong index
Change-Id: I81a6dcca634d3d30f0b101baabe4093fb01123d0
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/18236
Integration-Tests: Jenkins <[email protected]>
Tested-by: Jenkins <[email protected]>
Reviewed-by: <[email protected]>
Reviewed-by: Vijay Sarathy <[email protected]>
---
.../asterix/optimizer/rules/cbo/JoinEnum.java | 24 ++++++++++
.../asterix/optimizer/rules/cbo/JoinNode.java | 19 ++++++--
.../apache/asterix/optimizer/rules/cbo/Stats.java | 54 +++++++++++++---------
.../hints-use-index/hints-use-index-16.plan | 4 +-
4 files changed, 73 insertions(+), 28 deletions(-)
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 e419eea068..951648aa3b 100644
---
a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java
+++
b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java
@@ -30,6 +30,7 @@ import java.util.Set;
import org.apache.asterix.common.annotations.IndexedNLJoinExpressionAnnotation;
import
org.apache.asterix.common.annotations.SecondaryIndexSearchPreferenceAnnotation;
+import
org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
import org.apache.asterix.common.exceptions.AsterixException;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.metadata.declared.DataSource;
@@ -384,6 +385,29 @@ public class JoinEnum {
return false;
}
+ public SkipSecondaryIndexSearchExpressionAnnotation
findSkipIndexHint(AbstractFunctionCallExpression condition) {
+ if
(condition.getFunctionIdentifier().equals(AlgebricksBuiltinFunctions.AND)) {
+ for (int i = 0; i < condition.getArguments().size(); i++) {
+ ILogicalExpression expr =
condition.getArguments().get(i).getValue();
+ if
(expr.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
+ AbstractFunctionCallExpression AFCexpr =
(AbstractFunctionCallExpression) expr;
+ SkipSecondaryIndexSearchExpressionAnnotation skipAnno =
+
AFCexpr.getAnnotation(SkipSecondaryIndexSearchExpressionAnnotation.class);
+ if (skipAnno != null) {
+ return skipAnno;
+ }
+ }
+ }
+ } else if
(condition.getExpressionTag().equals(LogicalExpressionTag.FUNCTION_CALL)) {
+ SkipSecondaryIndexSearchExpressionAnnotation skipAnno =
+
condition.getAnnotation(SkipSecondaryIndexSearchExpressionAnnotation.class);
+ if (skipAnno != null) {
+ return skipAnno;
+ }
+ }
+ return null;
+ }
+
protected int findJoinNodeIndexByName(String name) {
for (int i = 1; i <= this.numberOfTerms; i++) {
if (name.equals(jnArray[i].datasetNames.get(0))) {
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 4543190f27..37212bae7e 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
@@ -21,8 +21,10 @@ package org.apache.asterix.optimizer.rules.cbo;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -546,9 +548,20 @@ public class JoinNode {
for (int i = 0; i < IndexCostInfo.size(); i++) {
if (IndexCostInfo.get(i).second == -1.0) {
AbstractFunctionCallExpression afce =
IndexCostInfo.get(i).third;
- // this index has to be skipped, so find the corresponding
expression
- EnumerateJoinsRule.setAnnotation(afce,
SkipSecondaryIndexSearchExpressionAnnotation
-
.newInstance(Collections.singleton(IndexCostInfo.get(i).first.getIndexName())));
+ SkipSecondaryIndexSearchExpressionAnnotation skipAnno =
joinEnum.findSkipIndexHint(afce);
+ Collection<String> indexNames = new HashSet<>();
+ if (skipAnno != null && skipAnno.getIndexNames() != null) {
+ indexNames.addAll(skipAnno.getIndexNames());
+ }
+ if (indexNames.isEmpty()) {
+ // this index has to be skipped, so find the corresponding
expression
+ EnumerateJoinsRule.setAnnotation(afce,
SkipSecondaryIndexSearchExpressionAnnotation
+
.newInstance(Collections.singleton(IndexCostInfo.get(i).first.getIndexName())));
+ } else {
+ indexNames.add(IndexCostInfo.get(i).first.getIndexName());
+ EnumerateJoinsRule.setAnnotation(afce,
+
SkipSecondaryIndexSearchExpressionAnnotation.newInstance(indexNames));
+ }
}
}
}
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 254d36496d..785da69b66 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
@@ -446,33 +446,41 @@ public class Stats {
List<List<IAObject>> result;
parent.getInputs().get(0).setValue(deepCopyofScan);
- if (numSubplans == 1 && nonSubplanSelects == 0) {
- AggregateOperator aggOp = findAggOp(selOp, exp);
- if (aggOp.getExpressions().size() > 1) {
- // ANY and EVERY IN query; for selectivity purposes, we need
to transform this into a ANY IN query
- SelectOperator newSelOp = (SelectOperator)
OperatorManipulationUtil.bottomUpCopyOperators(selOp);
- aggOp = findAggOp(newSelOp, exp);
- ILogicalOperator input = aggOp.getInputs().get(0).getValue();
- SelectOperator condition = (SelectOperator)
OperatorManipulationUtil
-
.bottomUpCopyOperators(AbstractOperatorFromSubplanRewrite.getSelectFromPlan(aggOp));
- //push this condition below aggOp.
- aggOp.getInputs().get(0).setValue(condition);
- condition.getInputs().get(0).setValue(input);
- ILogicalExpression newExp2 =
newSelOp.getCondition().getValue();
- if (newExp2.getExpressionTag() ==
LogicalExpressionTag.FUNCTION_CALL) {
- AbstractFunctionCallExpression afce =
(AbstractFunctionCallExpression) newExp2;
-
afce.getArguments().get(1).setValue(ConstantExpression.TRUE);
+
+ if (numSelects == 1 && numSubplans == 0) { // just switch the
predicates; the simplest case. There should be no other case if subplans were
canonical
+ ILogicalExpression saveExprs = selOp.getCondition().getValue();
+ selOp.getCondition().setValue(exp);
+ result = runSamplingQuery(optCtx, selOp);
+ selOp.getCondition().setValue(saveExprs);
+ } else {
+ if (numSubplans == 1 && nonSubplanSelects == 0) {
+ AggregateOperator aggOp = findAggOp(selOp, exp);
+ if (aggOp.getExpressions().size() > 1) {
+ // ANY and EVERY IN query; for selectivity purposes, we
need to transform this into a ANY IN query
+ SelectOperator newSelOp = (SelectOperator)
OperatorManipulationUtil.bottomUpCopyOperators(selOp);
+ aggOp = findAggOp(newSelOp, exp);
+ ILogicalOperator input =
aggOp.getInputs().get(0).getValue();
+ SelectOperator condition = (SelectOperator)
OperatorManipulationUtil
+
.bottomUpCopyOperators(AbstractOperatorFromSubplanRewrite.getSelectFromPlan(aggOp));
+ //push this condition below aggOp.
+ aggOp.getInputs().get(0).setValue(condition);
+ condition.getInputs().get(0).setValue(input);
+ ILogicalExpression newExp2 =
newSelOp.getCondition().getValue();
+ if (newExp2.getExpressionTag() ==
LogicalExpressionTag.FUNCTION_CALL) {
+ AbstractFunctionCallExpression afce =
(AbstractFunctionCallExpression) newExp2;
+
afce.getArguments().get(1).setValue(ConstantExpression.TRUE);
+ }
+ result = runSamplingQuery(optCtx, newSelOp); // no need to
switch anything
+ } else {
+ result = runSamplingQuery(optCtx, selOp);
}
- result = runSamplingQuery(optCtx, newSelOp); // no need to
switch anything
} else {
+ SelectOperator selOp2 = findSelectOpWithExpr(selOp, exp);
+ List<ILogicalExpression> selExprs;
+ selExprs = storeSelectConditionsAndMakeThemTrue(selOp,
selOp2); // all these will be marked true and will be resorted later.
result = runSamplingQuery(optCtx, selOp);
+ restoreAllSelectConditions(selOp, selExprs, selOp2);
}
- } else {
- SelectOperator selOp2 = findSelectOpWithExpr(selOp, exp);
- List<ILogicalExpression> selExprs;
- selExprs = storeSelectConditionsAndMakeThemTrue(selOp, selOp2); //
all these will be marked true and will be resorted later.
- result = runSamplingQuery(optCtx, selOp);
- restoreAllSelectConditions(selOp, selExprs, selOp2);
}
double predicateCardinality = findPredicateCardinality(result, false);
diff --git
a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan
b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan
index 00ba0d7ded..725e81e65f 100644
---
a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan
+++
b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/btree-index-selection/hints-use-index/hints-use-index-16.plan
@@ -9,11 +9,11 @@
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- BTREE_SEARCH (test.tenk.tenk) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- STABLE_SORT [$$31(ASC)] |PARTITIONED|
+ -- STABLE_SORT [$$28(ASC)] |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- STREAM_PROJECT |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
- -- BTREE_SEARCH (test.tenk.idx_1k_2k)
|PARTITIONED|
+ -- BTREE_SEARCH (test.tenk.idx_2k) |PARTITIONED|
-- ONE_TO_ONE_EXCHANGE |PARTITIONED|
-- ASSIGN |PARTITIONED|
-- EMPTY_TUPLE_SOURCE |PARTITIONED|