You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by mb...@apache.org on 2025/09/09 00:06:56 UTC
(asterixdb) branch master updated: [ASTERIXDB-3632]: Add Index Advisor
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 3483159e6d [ASTERIXDB-3632]: Add Index Advisor
3483159e6d is described below
commit 3483159e6d5fbce8551eb0777b5c034ca6eeba7a
Author: preetham0202 <pr...@couchbase.com>
AuthorDate: Fri May 9 16:44:37 2025 +0530
[ASTERIXDB-3632]: Add Index Advisor
- user model changes: yes
- storage format changes: no
- interface changes: no
Ext-ref: MB-66492
Change-Id: Iac773ebb49bdde18cfd340ef15d483dc324bdced
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/19763
Integration-Tests: Jenkins <je...@fulliautomatix.ics.uci.edu>
Tested-by: Ali Alsuliman <al...@gmail.com>
Reviewed-by: Ali Alsuliman <al...@gmail.com>
---
.../compiler/provider/DefaultRuleSetFactory.java | 17 ++
.../asterix/compiler/provider/IRuleSetFactory.java | 9 +
.../optimizer/base/AsterixOptimizationContext.java | 5 +-
.../asterix/optimizer/base/RuleCollections.java | 2 +
.../am/AbstractIntroduceAccessMethodRule.java | 9 +-
.../rules/am/IntroduceJoinAccessMethodRule.java | 16 +-
.../rules/am/IntroduceSelectAccessMethodRule.java | 17 +-
.../array/AbstractOperatorFromSubplanRewrite.java | 8 +-
.../optimizer/rules/cbo/EnumerateJoinsRule.java | 34 ++-
.../asterix/optimizer/rules/cbo/JoinEnum.java | 11 +-
.../asterix/optimizer/rules/cbo/JoinNode.java | 57 ++---
.../apache/asterix/optimizer/rules/cbo/Stats.java | 9 +-
.../cbo/indexadvisor/AbstractAdvisorPlanNode.java | 24 ++-
.../rules/cbo/indexadvisor/AdviseIndexRule.java | 158 ++++++++++++++
.../cbo/indexadvisor/AdvisorConditionParser.java | 229 +++++++++++++++++++++
.../cbo/indexadvisor/AdvisorJoinPlanNode.java | 61 ++++++
.../rules/cbo/indexadvisor/AdvisorPlanParser.java | 114 ++++++++++
.../cbo/indexadvisor/AdvisorScanPlanNode.java | 67 ++++++
.../rules/cbo/indexadvisor/CBOPlanStateTree.java | 50 +++++
.../rules/cbo/indexadvisor/FakeIndex.java | 45 ++++
.../rules/cbo/indexadvisor/FakeIndexProvider.java | 176 ++++++++++++++++
.../rules/cbo/indexadvisor/IIndexEnumerator.java | 80 +++++++
.../rules/cbo/indexadvisor/JoinFilter.java | 13 +-
.../cbo/indexadvisor/JoinFilterCondition.java | 57 +++++
.../rules/cbo/indexadvisor/ScanFilter.java | 11 +-
.../cbo/indexadvisor/ScanFilterCondition.java | 26 ++-
.../apache/asterix/api/common/APIFramework.java | 38 +++-
.../result/fields/IndexAdviseResultsPrinter.java | 57 +++++
.../asterix/app/translator/QueryTranslator.java | 2 +-
.../org/apache/asterix/utils/FeedOperations.java | 2 +-
.../queries_sqlpp/cbo-join/CBOJoinQueries.xml | 26 ++-
.../join-advise/join-advise.1.ddl.sqlpp | 14 +-
.../join-advise/join-advise.2.update.sqlpp | 19 +-
.../join-advise/join-advise.3.update.sqlpp | 12 +-
.../join-advise/join-advise.4.query.sqlpp | 16 +-
.../nested-fields/nested-fields.1.ddl.sqlpp | 17 +-
.../nested-fields/nested-fields.2.update.sqlpp | 19 +-
.../nested-fields/nested-fields.3.update.sqlpp | 12 +-
.../nested-fields/nested-fields.4.query.sqlpp | 17 +-
.../simple-advise/simple-advise.1.ddl.sqlpp | 16 +-
.../simple-advise/simple-advise.2.update.sqlpp | 19 +-
.../simple-advise/simple-advise.3.update.sqlpp | 12 +-
.../simple-advise/simple-advise.4.query.sqlpp | 16 +-
.../simple-advise1/simple-advise1.1.ddl.sqlpp | 14 +-
.../simple-advise1/simple-advise1.2.update.sqlpp | 19 +-
.../simple-advise1/simple-advise1.3.update.sqlpp | 13 +-
.../simple-advise1/simple-advise1.4.query.sqlpp | 14 +-
.../simple-advise1/simple-advise1.5.query.sqlpp | 14 +-
.../simple-advise2/simple-advise2.1.ddl.sqlpp | 14 +-
.../simple-advise2/simple-advise2.2.update.sqlpp | 19 +-
.../simple-advise2/simple-advise2.3.update.sqlpp | 12 +-
.../simple-advise2/simple-advise2.4.query.sqlpp | 19 +-
.../index-advisor/join-advise/join-advise.4.adm | 1 +
.../nested-fields/nested-fields.4.adm | 1 +
.../simple-advise/simple-advise.4.adm | 1 +
.../simple-advise1/simple-advise1.4.adm | 1 +
.../simple-advise1/simple-advise1.5.adm | 1 +
.../simple-advise2/simple-advise2.4.adm | 1 +
.../asterix/lang/common/statement/Query.java | 21 +-
.../asterix/lang/common/util/ExpressionUtils.java | 2 +-
.../CloneAndSubstituteVariablesVisitor.java | 2 +-
.../visitor/SqlppCopyToRewriteVisitor.java | 2 +-
.../asterix/lang/sqlpp/util/SqlppRewriteUtil.java | 2 +-
.../lang/sqlpp/visitor/DeepCopyVisitor.java | 4 +-
.../sqlpp/visitor/SqlppDeleteRewriteVisitor.java | 2 +-
.../asterix-lang-sqlpp/src/main/javacc/SQLPP.jj | 22 +-
.../asterix/metadata/declared/IIndexProvider.java | 19 +-
.../metadata/declared/MetadataProvider.java | 4 +-
.../api/AbstractCompilerFactoryBuilder.java | 6 +
.../api/HeuristicCompilerFactoryBuilder.java | 21 +-
.../algebricks/compiler/api/ICompilerFactory.java | 4 +-
.../core/algebra/base/IOptimizationContext.java | 3 +
.../algebricks/core/algebra/base/IndexAdvisor.java | 147 +++++++++++++
.../base/AlgebricksOptimizationContext.java | 12 +-
.../rewriter/base/IOptimizationContextFactory.java | 4 +-
75 files changed, 1711 insertions(+), 329 deletions(-)
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
index fa1a174e3a..b74363d1c9 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/DefaultRuleSetFactory.java
@@ -19,6 +19,7 @@
package org.apache.asterix.compiler.provider;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import org.apache.asterix.common.dataflow.ICcApplicationContext;
@@ -46,6 +47,10 @@ public class DefaultRuleSetFactory implements IRuleSetFactory {
ICcApplicationContext appCtx) {
if (ruleSetKind == RuleSetKind.SAMPLING) {
return buildLogicalSampling();
+ } else if (ruleSetKind == RuleSetKind.QUERY) {
+ return getLogicalRewrites(appCtx);
+ } else if (ruleSetKind == RuleSetKind.LOGICAL_ADVISOR) {
+ return getLogicalRewrites(appCtx);
} else {
throw new IllegalArgumentException(String.valueOf(ruleSetKind));
}
@@ -57,6 +62,18 @@ public class DefaultRuleSetFactory implements IRuleSetFactory {
return buildPhysical(appCtx, CostMethods::new);
}
+ @Override
+ public List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> getPhysicalRewrites(IRuleSetKind ruleSetKind,
+ ICcApplicationContext appCtx) {
+ if (ruleSetKind == RuleSetKind.QUERY) {
+ return buildPhysical(appCtx, CostMethods::new);
+ } else if (ruleSetKind == RuleSetKind.SAMPLING) {
+ return buildPhysical(appCtx, CostMethods::new);
+ } else {
+ return Collections.emptyList();
+ }
+ }
+
public static List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> buildLogical(
ICcApplicationContext appCtx) {
List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> defaultLogicalRewrites = new ArrayList<>();
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/IRuleSetFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/IRuleSetFactory.java
index c643d21450..977875924d 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/IRuleSetFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/IRuleSetFactory.java
@@ -29,6 +29,8 @@ import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
public interface IRuleSetFactory {
enum RuleSetKind implements IRuleSetKind {
+ QUERY,
+ LOGICAL_ADVISOR,
SAMPLING
}
@@ -47,4 +49,11 @@ public interface IRuleSetFactory {
* @return the physical rewrites
*/
List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> getPhysicalRewrites(ICcApplicationContext appCtx);
+
+ /**
+ * @return the physical rewrites of the specified kind
+ */
+ List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>> getPhysicalRewrites(IRuleSetKind ruleSetKind,
+ ICcApplicationContext appCtx);
+
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
index 7c6b150ed5..047394b7d4 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/AsterixOptimizationContext.java
@@ -27,6 +27,7 @@ import org.apache.asterix.common.metadata.MetadataConstants;
import org.apache.asterix.metadata.declared.DataSource;
import org.apache.asterix.metadata.declared.FunctionDataSource;
import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
@@ -51,10 +52,10 @@ public final class AsterixOptimizationContext extends AlgebricksOptimizationCont
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer nullableTypeComputer,
IConflictingTypeResolver conflictingTypeResovler, PhysicalOptimizationConfig physicalOptimizationConfig,
AlgebricksPartitionConstraint clusterLocations, IPlanPrettyPrinter prettyPrinter,
- IWarningCollector warningCollector) {
+ IWarningCollector warningCollector, IndexAdvisor indexAdvisor) {
super(optContextFactory, varCounter, expressionEvalSizeComputer, mergeAggregationExpressionFactory,
expressionTypeComputer, nullableTypeComputer, conflictingTypeResovler, physicalOptimizationConfig,
- clusterLocations, prettyPrinter, warningCollector);
+ clusterLocations, prettyPrinter, warningCollector, indexAdvisor);
dataSourceMap = new Int2ObjectOpenHashMap<>();
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
index d786e9d371..e14cbf32b9 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java
@@ -106,6 +106,7 @@ import org.apache.asterix.optimizer.rules.am.IntroducePrimaryIndexForAggregation
import org.apache.asterix.optimizer.rules.am.IntroduceSelectAccessMethodRule;
import org.apache.asterix.optimizer.rules.cbo.EnumerateJoinsRule;
import org.apache.asterix.optimizer.rules.cbo.JoinEnum;
+import org.apache.asterix.optimizer.rules.cbo.indexadvisor.AdviseIndexRule;
import org.apache.asterix.optimizer.rules.subplan.AsterixMoveFreeVariableOperatorOutOfSubplanRule;
import org.apache.asterix.optimizer.rules.subplan.InlineSubplanInputForNestedTupleSourceRule;
import org.apache.asterix.optimizer.rules.temporal.TranslateIntervalExpressionRule;
@@ -336,6 +337,7 @@ public final class RuleCollections {
accessMethod.add(new RemoveUnusedOneToOneEquiJoinRule());
accessMethod.add(new PushSimilarityFunctionsBelowJoin());
accessMethod.add(new RemoveUnusedAssignAndAggregateRule());
+ accessMethod.add(new AdviseIndexRule());
return accessMethod;
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
index 24ef2d7a55..2d97258d01 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/AbstractIntroduceAccessMethodRule.java
@@ -39,6 +39,7 @@ import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.common.metadata.MetadataUtil;
import org.apache.asterix.dataflow.data.common.ExpressionTypeComputer;
import org.apache.asterix.metadata.declared.DataSourceId;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Index;
@@ -87,6 +88,7 @@ import com.google.common.base.Strings;
*/
public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRewriteRule {
protected MetadataProvider metadataProvider;
+ protected IIndexProvider indexProvider;
public abstract Map<FunctionIdentifier, List<IAccessMethod>> getAccessMethods();
@@ -109,8 +111,9 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
return false;
}
- protected void setMetadataDeclarations(IOptimizationContext context) {
+ protected void setMetadataIndexDeclarations(IOptimizationContext context, IIndexProvider indexProvider) {
metadataProvider = (MetadataProvider) context.getMetadataProvider();
+ this.indexProvider = indexProvider;
}
protected void fillSubTreeIndexExprs(OptimizableOperatorSubTree subTree,
@@ -882,7 +885,7 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
LogicalVariable datasetMetaVar = null;
if (subTree.getDataSourceType() != DataSourceType.COLLECTION_SCAN
&& subTree.getDataSourceType() != DataSourceType.INDEXONLY_PLAN_SECONDARY_INDEX_LOOKUP) {
- datasetIndexes = metadataProvider.getDatasetIndexes(subTree.getDataset().getDatabaseName(),
+ datasetIndexes = indexProvider.getDatasetIndexes(subTree.getDataset().getDatabaseName(),
subTree.getDataset().getDataverseName(), subTree.getDataset().getDatasetName());
List<LogicalVariable> datasetVars = subTree.getDataSourceVariables();
if (subTree.getDataset().hasMetaPart()) {
@@ -1200,6 +1203,6 @@ public abstract class AbstractIntroduceAccessMethodRule implements IAlgebraicRew
String database = srcId.getDatabaseName();
DataverseName dataverseName = srcId.getDataverseName();
String datasourceName = srcId.getDatasourceName();
- return metadataProvider.getIndex(database, dataverseName, datasourceName, datasourceName);
+ return indexProvider.getIndex(database, dataverseName, datasourceName, datasourceName);
}
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
index b7ae1b0edb..5bc1e90b5d 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceJoinAccessMethodRule.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.metadata.entities.Dataset;
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.optimizer.rules.am.array.IIntroduceAccessMethodRuleLocalRewrite;
@@ -121,7 +122,12 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
throws AlgebricksException {
clear();
- setMetadataDeclarations(context);
+ boolean adviseIndex = context.getIndexAdvisor().getAdvise();
+ if (adviseIndex) {
+ setMetadataIndexDeclarations(context, (IIndexProvider) context.getIndexAdvisor().getFakeIndexProvider());
+ } else {
+ setMetadataIndexDeclarations(context, (IIndexProvider) context.getMetadataProvider());
+ }
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
@@ -160,10 +166,10 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
}
public boolean checkApplicable(Mutable<ILogicalOperator> opRef, IOptimizationContext context,
- List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs)
- throws AlgebricksException {
+ List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs,
+ IIndexProvider indexProvider) throws AlgebricksException {
clear();
- setMetadataDeclarations(context);
+ setMetadataIndexDeclarations(context, indexProvider);
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
@@ -332,7 +338,7 @@ public class IntroduceJoinAccessMethodRule extends AbstractIntroduceAccessMethod
}
if (continueCheck && context.getPhysicalOptimizationConfig().isArrayIndexEnabled()
- && JoinFromSubplanRewrite.isApplicableForRewriteCursory(metadataProvider, joinOp)) {
+ && JoinFromSubplanRewrite.isApplicableForRewriteCursory(indexProvider, joinOp)) {
// If there exists a SUBPLAN in our plan, and we are conditioning on a variable, attempt to rewrite
// this subplan to allow an array-index AM to be introduced. If successful, this rewrite will transform
// into an index-nested-loop-join. This rewrite is to be used for pushing the UNNESTs and ASSIGNs from
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
index dbb164a24f..8257ec5327 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/IntroduceSelectAccessMethodRule.java
@@ -30,6 +30,7 @@ import org.apache.asterix.common.cluster.PartitioningProperties;
import org.apache.asterix.common.config.DatasetConfig;
import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.optimizer.rules.am.array.IIntroduceAccessMethodRuleLocalRewrite;
@@ -155,7 +156,13 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
throws AlgebricksException {
clear();
- setMetadataDeclarations(context);
+
+ boolean adviseIndex = context.getIndexAdvisor().getAdvise();
+ if (adviseIndex) {
+ setMetadataIndexDeclarations(context, (IIndexProvider) context.getIndexAdvisor().getFakeIndexProvider());
+ } else {
+ setMetadataIndexDeclarations(context, (IIndexProvider) context.getMetadataProvider());
+ }
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
@@ -200,10 +207,10 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
}
public boolean checkApplicable(Mutable<ILogicalOperator> opRef, IOptimizationContext context,
- List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs)
- throws AlgebricksException {
+ List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs,
+ IIndexProvider indexProvider) throws AlgebricksException {
clear();
- setMetadataDeclarations(context);
+ setMetadataIndexDeclarations(context, indexProvider);
AbstractLogicalOperator op = (AbstractLogicalOperator) opRef.getValue();
@@ -507,7 +514,7 @@ public class IntroduceSelectAccessMethodRule extends AbstractIntroduceAccessMeth
}
if (continueCheck && context.getPhysicalOptimizationConfig().isArrayIndexEnabled()
- && SelectFromSubplanRewrite.isApplicableForRewriteCursory(metadataProvider, selectOp)) {
+ && SelectFromSubplanRewrite.isApplicableForRewriteCursory(indexProvider, selectOp)) {
// If there exists a composite atomic-array index, our conjuncts will be split across multiple
// SELECTs. This rewrite is to be used **solely** for the purpose of changing a DATA-SCAN into a
// non-index-only plan branch. No nodes introduced from this rewrite will be used beyond this point.
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/array/AbstractOperatorFromSubplanRewrite.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/array/AbstractOperatorFromSubplanRewrite.java
index 38d6982bb9..04d163ec32 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/array/AbstractOperatorFromSubplanRewrite.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/am/array/AbstractOperatorFromSubplanRewrite.java
@@ -28,7 +28,7 @@ import org.apache.asterix.common.exceptions.CompilationException;
import org.apache.asterix.common.exceptions.ErrorCode;
import org.apache.asterix.common.metadata.DataverseName;
import org.apache.asterix.metadata.declared.DataSourceId;
-import org.apache.asterix.metadata.declared.MetadataProvider;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.om.base.AInt16;
import org.apache.asterix.om.base.AInt32;
import org.apache.asterix.om.base.AInt64;
@@ -73,7 +73,7 @@ abstract public class AbstractOperatorFromSubplanRewrite<T> implements IIntroduc
private IOptimizationContext context;
private SourceLocation sourceLocation;
- public static boolean isApplicableForRewriteCursory(MetadataProvider metadataProvider, ILogicalOperator workingOp)
+ public static boolean isApplicableForRewriteCursory(IIndexProvider indexProvider, ILogicalOperator workingOp)
throws AlgebricksException {
boolean isApplicableForRewrite = false;
if (workingOp.getOperatorTag() == LogicalOperatorTag.DATASOURCESCAN) {
@@ -82,14 +82,14 @@ abstract public class AbstractOperatorFromSubplanRewrite<T> implements IIntroduc
DataverseName dataverseName = srcId.getDataverseName();
String database = srcId.getDatabaseName();
String datasetName = srcId.getDatasourceName();
- if (metadataProvider.getDatasetIndexes(database, dataverseName, datasetName).stream()
+ if (indexProvider.getDatasetIndexes(database, dataverseName, datasetName).stream()
.anyMatch(i -> i.getIndexType() == DatasetConfig.IndexType.ARRAY)) {
return true;
}
}
for (Mutable<ILogicalOperator> inputOp : workingOp.getInputs()) {
- isApplicableForRewrite |= isApplicableForRewriteCursory(metadataProvider, inputOp.getValue());
+ isApplicableForRewrite |= isApplicableForRewriteCursory(indexProvider, inputOp.getValue());
}
return isApplicableForRewrite;
}
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 8406520070..6e4208d14e 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
@@ -28,7 +28,11 @@ import java.util.Map;
import org.apache.asterix.common.annotations.IndexedNLJoinExpressionAnnotation;
import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.optimizer.rules.cbo.indexadvisor.AdvisorPlanParser;
+import org.apache.asterix.optimizer.rules.cbo.indexadvisor.CBOPlanStateTree;
+import org.apache.asterix.optimizer.rules.cbo.indexadvisor.FakeIndexProvider;
import org.apache.asterix.translator.SqlppExpressionToPlanTranslator;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableBoolean;
@@ -107,7 +111,9 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
private List<Triple<ILogicalOperator, ILogicalOperator, List<ILogicalOperator>>> modifyUnnestInfo;
private final Map<DataSourceScanOperator, Boolean> fakeLeafInputsMap = new HashMap();
- ILogicalOperator newRootAfterUnnest = null;
+ private ILogicalOperator newRootAfterUnnest = null;
+
+ private IIndexProvider indexProvider;
public EnumerateJoinsRule(JoinEnum joinEnum) {
this.joinEnum = joinEnum;
@@ -116,6 +122,10 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
rootOrderByOp = null;
}
+ private void setIndexProvider(IIndexProvider indexProvider) {
+ this.indexProvider = indexProvider;
+ }
+
@Override
public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
return false;
@@ -170,8 +180,17 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
return false;
}
- IPlanPrettyPrinter pp = context.getPrettyPrinter();
+ boolean adviseIndex = context.getIndexAdvisor().getAdvise();
+ if (adviseIndex) {
+ CBOPlanStateTree cboPlanStateTree = AdvisorPlanParser.getCBOPlanState(opRef, context);
+ FakeIndexProvider fakeIndexProvider = new FakeIndexProvider(cboPlanStateTree);
+ context.getIndexAdvisor().setFakeIndexProvider(fakeIndexProvider);
+ setIndexProvider(fakeIndexProvider);
+ } else {
+ setIndexProvider((IIndexProvider) context.getMetadataProvider());
+ }
+ IPlanPrettyPrinter pp = context.getPrettyPrinter();
String viewInPlan;
if (LOGGER.isTraceEnabled()) {
viewInPlan = new ALogicalPlanImpl(opRef).toString(); //useful when debugging
@@ -256,8 +275,7 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
joinEnum.initEnum((AbstractLogicalOperator) op, cboMode, cboTestMode, numberOfFromTerms, leafInputs, allJoinOps,
assignOps, outerJoinsDependencyList, buildSets, varLeafInputIds, unnestOpsInfo,
dataScanAndGroupByDistinctOps, rootGroupByDistinctOp, rootOrderByOp, resultAndJoinVars,
- fakeLeafInputsMap, context);
-
+ fakeLeafInputsMap, context, indexProvider);
if (cboMode) {
if (!doAllDataSourcesHaveSamples(leafInputs, context)) {
return cleanUp();
@@ -729,7 +747,7 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
}
}
- private boolean joinClause(ILogicalOperator op) {
+ public static boolean joinClause(ILogicalOperator op) {
if (op.getOperatorTag() == LogicalOperatorTag.INNERJOIN)
return true;
if (op.getOperatorTag() == LogicalOperatorTag.LEFTOUTERJOIN)
@@ -764,7 +782,7 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
* Should not see any kind of joins here. store the emptyTupeSourceOp and DataSource operators.
* Each leaf input will normally have both, but sometimes only emptyTupeSourceOp will be present (in lists)
*/
- private Pair<EmptyTupleSourceOperator, DataSourceScanOperator> containsLeafInputOnly(ILogicalOperator op) {
+ public static Pair<EmptyTupleSourceOperator, DataSourceScanOperator> containsLeafInputOnly(ILogicalOperator op) {
DataSourceScanOperator dataSourceOp = null;
ILogicalOperator currentOp = op;
while (currentOp.getInputs().size() == 1) {
@@ -797,7 +815,7 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
}
// An internal edge must contain only assigns followed by an inner join. Not sure if there will be other ops between joins
- private int numVarRefExprs(AssignOperator aOp) {
+ public static int numVarRefExprs(AssignOperator aOp) {
List<Mutable<ILogicalExpression>> exprs = aOp.getExpressions();
int count = 0;
for (Mutable<ILogicalExpression> exp : exprs) {
@@ -828,7 +846,7 @@ public class EnumerateJoinsRule implements IAlgebraicRewriteRule {
return (joinClause(op));
}
- private ILogicalOperator skipPastAssigns(ILogicalOperator nextOp) {
+ public static ILogicalOperator skipPastAssigns(ILogicalOperator nextOp) {
while (nextOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
nextOp = nextOp.getInputs().get(0).getValue();
}
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 16518c2a55..30b513bd10 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
@@ -39,6 +39,7 @@ import org.apache.asterix.lang.common.util.FunctionUtil;
import org.apache.asterix.metadata.declared.DataSource;
import org.apache.asterix.metadata.declared.DataSourceId;
import org.apache.asterix.metadata.declared.DatasetDataSource;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.metadata.declared.MetadataProvider;
import org.apache.asterix.metadata.declared.SampleDataSource;
import org.apache.asterix.metadata.entities.Index;
@@ -144,6 +145,7 @@ public class JoinEnum {
protected ICostMethods costMethods;
List<LogicalVariable> resultAndJoinVars;
Map<DataSourceScanOperator, Boolean> fakeLeafInputsMap;
+ IIndexProvider indexProvider;
public JoinEnum() {
}
@@ -155,8 +157,8 @@ public class JoinEnum {
List<List<List<ILogicalOperator>>> unnestOpsInfo,
HashMap<DataSourceScanOperator, ILogicalOperator> dataScanAndGroupByDistinctOps,
ILogicalOperator grpByDistinctOp, ILogicalOperator orderByOp, List<LogicalVariable> resultAndJoinVars,
- Map<DataSourceScanOperator, Boolean> fakeLeafInputsMap, IOptimizationContext context)
- throws AsterixException {
+ Map<DataSourceScanOperator, Boolean> fakeLeafInputsMap, IOptimizationContext context,
+ IIndexProvider indexProvider) throws AsterixException {
this.singleDatasetPreds = new ArrayList<>();
this.joinConditions = new ArrayList<>();
this.joinHints = new HashMap<>();
@@ -187,6 +189,7 @@ public class JoinEnum {
initCostHandleAndJoinNodes(context);
this.allTabsJnNum = 1; // keeps track of where the final join Node will be. In case of bushy plans, this may not always be the last join nod e.
this.maxBits = 1;
+ this.indexProvider = indexProvider;
}
protected void initCostHandleAndJoinNodes(IOptimizationContext context) {
@@ -992,7 +995,7 @@ public class JoinEnum {
JoinNode jnIJ = jnArray[addPlansToThisJn];
jnIJ.jnArrayIndex = addPlansToThisJn;
- jnIJ.addMultiDatasetPlans(jnI, jnJ);
+ jnIJ.addMultiDatasetPlans(jnI, jnJ, indexProvider);
if (forceJoinOrderMode && level > cboFullEnumLevel) {
break;
}
@@ -1187,7 +1190,7 @@ public class JoinEnum {
return PlanNode.NO_PLAN;
}
// We may not add any index plans, so need to check for NO_PLAN
- jn.addIndexAccessPlans(EnumerateJoinsRule.removeTrue(leafInput));
+ jn.addIndexAccessPlans(EnumerateJoinsRule.removeTrue(leafInput), indexProvider);
}
return this.numberOfTerms;
}
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 5cbb6f80e7..2abad0618d 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
@@ -37,6 +37,7 @@ import org.apache.asterix.common.annotations.IndexedNLJoinExpressionAnnotation;
import org.apache.asterix.common.annotations.SkipSecondaryIndexSearchExpressionAnnotation;
import org.apache.asterix.common.config.DatasetConfig;
import org.apache.asterix.metadata.declared.DatasetDataSource;
+import org.apache.asterix.metadata.declared.IIndexProvider;
import org.apache.asterix.metadata.declared.SampleDataSource;
import org.apache.asterix.metadata.entities.Index;
import org.apache.asterix.om.base.IAObject;
@@ -916,7 +917,8 @@ public class JoinNode {
return changes;
}
- protected void addIndexAccessPlans(ILogicalOperator leafInput) throws AlgebricksException {
+ protected void addIndexAccessPlans(ILogicalOperator leafInput, IIndexProvider indexProvider)
+ throws AlgebricksException {
IntroduceSelectAccessMethodRule tmp = new IntroduceSelectAccessMethodRule();
List<Pair<IAccessMethod, Index>> chosenIndexes = new ArrayList<>();
Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new TreeMap<>();
@@ -927,8 +929,8 @@ public class JoinNode {
SelectOperator firstSelop = copySelExprsAndSetTrue(selExprs, selOpers, leafInput);
if (firstSelop != null) { // if there are no selects, then there is no question of index selections either.
firstSelop.getCondition().setValue(andAlltheExprs(selExprs));
- boolean index_access_possible =
- tmp.checkApplicable(new MutableObject<>(leafInput), joinEnum.optCtx, chosenIndexes, analyzedAMs);
+ boolean index_access_possible = tmp.checkApplicable(new MutableObject<>(leafInput), joinEnum.optCtx,
+ chosenIndexes, analyzedAMs, indexProvider);
restoreSelExprs(selExprs, selOpers);
if (index_access_possible) {
costAndChooseIndexPlans(leafInput, analyzedAMs);
@@ -980,8 +982,8 @@ public class JoinNode {
}
private boolean nestedLoopsApplicable(ILogicalExpression joinExpr, boolean outerJoin,
- List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs)
- throws AlgebricksException {
+ List<Pair<IAccessMethod, Index>> chosenIndexes, Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs,
+ IIndexProvider indexProvider) throws AlgebricksException {
if (joinExpr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
return false;
@@ -1037,14 +1039,15 @@ public class JoinNode {
// Now call the rewritePre code
IntroduceJoinAccessMethodRule tmp = new IntroduceJoinAccessMethodRule();
boolean retVal = tmp.checkApplicable(new MutableObject<>(joinEnum.localJoinOp), joinEnum.optCtx, chosenIndexes,
- analyzedAMs);
+ analyzedAMs, indexProvider);
return retVal;
}
private boolean NLJoinApplicable(JoinNode leftJn, JoinNode rightJn, boolean outerJoin,
ILogicalExpression nestedLoopJoinExpr, List<Pair<IAccessMethod, Index>> chosenIndexes,
- Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs) throws AlgebricksException {
+ Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs, IIndexProvider indexProvider)
+ throws AlgebricksException {
if (leftJn.fake || rightJn.fake) {
return false;
@@ -1058,8 +1061,8 @@ public class JoinNode {
return false; // nested loop plan not possible.
}
- if (nestedLoopJoinExpr == null
- || !rightJn.nestedLoopsApplicable(nestedLoopJoinExpr, outerJoin, chosenIndexes, analyzedAMs)) {
+ if (nestedLoopJoinExpr == null || !rightJn.nestedLoopsApplicable(nestedLoopJoinExpr, outerJoin, chosenIndexes,
+ analyzedAMs, indexProvider)) {
return false;
}
@@ -1167,7 +1170,8 @@ public class JoinNode {
}
private int buildNLJoinPlan(PlanNode leftPlan, PlanNode rightPlan, ILogicalExpression nestedLoopJoinExpr,
- IndexedNLJoinExpressionAnnotation hintNLJoin, boolean outerJoin) throws AlgebricksException {
+ IndexedNLJoinExpressionAnnotation hintNLJoin, boolean outerJoin, IIndexProvider indexProvider)
+ throws AlgebricksException {
JoinNode leftJn = leftPlan.getJoinNode();
JoinNode rightJn = rightPlan.getJoinNode();
@@ -1186,7 +1190,8 @@ public class JoinNode {
List<Pair<IAccessMethod, Index>> chosenIndexes = new ArrayList<>();
Map<IAccessMethod, AccessMethodAnalysisContext> analyzedAMs = new TreeMap<>();
- if (!NLJoinApplicable(leftJn, rightJn, outerJoin, nestedLoopJoinExpr, chosenIndexes, analyzedAMs)) {
+ if (!NLJoinApplicable(leftJn, rightJn, outerJoin, nestedLoopJoinExpr, chosenIndexes, analyzedAMs,
+ indexProvider)) {
return PlanNode.NO_PLAN;
}
if (chosenIndexes.isEmpty()) {
@@ -1295,7 +1300,8 @@ public class JoinNode {
return PlanNode.NO_PLAN;
}
- protected void addMultiDatasetPlans(JoinNode leftJn, JoinNode rightJn) throws AlgebricksException {
+ protected void addMultiDatasetPlans(JoinNode leftJn, JoinNode rightJn, IIndexProvider indexProvider)
+ throws AlgebricksException {
PlanNode leftPlan, rightPlan;
if (level > joinEnum.cboFullEnumLevel) {
@@ -1307,7 +1313,7 @@ public class JoinNode {
leftPlan = joinEnum.allPlans.get(leftJn.cheapestPlanIndex);
rightPlan = joinEnum.allPlans.get(rightJn.cheapestPlanIndex);
- addMultiDatasetPlans(leftPlan, rightPlan);
+ addMultiDatasetPlans(leftPlan, rightPlan, indexProvider);
} else {
// FOR JOIN NODE LEVELS LESS THAN OR EQUAL TO THE LEVEL SPECIFIED FOR FULL ENUMERATION,
// DO FULL ENUMERATION => DO NOT PRUNE
@@ -1315,13 +1321,14 @@ public class JoinNode {
leftPlan = joinEnum.allPlans.get(leftPlanIndex);
for (int rightPlanIndex : rightJn.planIndexesArray) {
rightPlan = joinEnum.allPlans.get(rightPlanIndex);
- addMultiDatasetPlans(leftPlan, rightPlan);
+ addMultiDatasetPlans(leftPlan, rightPlan, indexProvider);
}
}
}
}
- protected void addMultiDatasetPlans(PlanNode leftPlan, PlanNode rightPlan) throws AlgebricksException {
+ protected void addMultiDatasetPlans(PlanNode leftPlan, PlanNode rightPlan, IIndexProvider indexProvider)
+ throws AlgebricksException {
JoinNode leftJn = leftPlan.getJoinNode();
JoinNode rightJn = rightPlan.getJoinNode();
@@ -1388,12 +1395,12 @@ public class JoinNode {
newJoinConditions);
} else if (hintNLJoin != null) {
validPlan = buildHintedNLJPlans(leftPlan, rightPlan, nestedLoopJoinExpr, hintNLJoin, outerJoin,
- newJoinConditions);
+ newJoinConditions, indexProvider);
}
if (!validPlan) {
// No join hints or inapplicable hinted plans, try all non hinted plans.
- buildAllNonHintedPlans(leftPlan, rightPlan, hashJoinExpr, nestedLoopJoinExpr, outerJoin);
+ buildAllNonHintedPlans(leftPlan, rightPlan, hashJoinExpr, nestedLoopJoinExpr, outerJoin, indexProvider);
}
//Reset as these might have changed when we tried the commutative joins.
@@ -1468,11 +1475,11 @@ public class JoinNode {
}
private boolean buildHintedNLJPlans(PlanNode leftPlan, PlanNode rightPlan, ILogicalExpression nestedLoopJoinExpr,
- IndexedNLJoinExpressionAnnotation hintNLJoin, boolean outerJoin, List<Integer> newJoinConditions)
- throws AlgebricksException {
+ IndexedNLJoinExpressionAnnotation hintNLJoin, boolean outerJoin, List<Integer> newJoinConditions,
+ IIndexProvider indexProvider) throws AlgebricksException {
int nljPlan, commutativeNljPlan;
nljPlan = commutativeNljPlan = PlanNode.NO_PLAN;
- nljPlan = buildNLJoinPlan(leftPlan, rightPlan, nestedLoopJoinExpr, hintNLJoin, outerJoin);
+ nljPlan = buildNLJoinPlan(leftPlan, rightPlan, nestedLoopJoinExpr, hintNLJoin, outerJoin, indexProvider);
// The indexnl hint may have been removed during applicability checking
// and is no longer available for a hintedNL plan.
@@ -1480,7 +1487,8 @@ public class JoinNode {
return false;
}
if (!joinEnum.forceJoinOrderMode || level <= joinEnum.cboFullEnumLevel) {
- commutativeNljPlan = buildNLJoinPlan(rightPlan, leftPlan, nestedLoopJoinExpr, hintNLJoin, outerJoin);
+ commutativeNljPlan =
+ buildNLJoinPlan(rightPlan, leftPlan, nestedLoopJoinExpr, hintNLJoin, outerJoin, indexProvider);
// The indexnl hint may have been removed during applicability checking
// and is no longer available for a hintedNL plan.
if (joinEnum.findNLJoinHint(newJoinConditions) == null) {
@@ -1511,7 +1519,8 @@ public class JoinNode {
}
private void buildAllNonHintedPlans(PlanNode leftPlan, PlanNode rightPlan, ILogicalExpression hashJoinExpr,
- ILogicalExpression nestedLoopJoinExpr, boolean outerJoin) throws AlgebricksException {
+ ILogicalExpression nestedLoopJoinExpr, boolean outerJoin, IIndexProvider indexProvider)
+ throws AlgebricksException {
buildHashJoinPlan(leftPlan, rightPlan, hashJoinExpr, null, outerJoin);
if (!joinEnum.forceJoinOrderMode || level <= joinEnum.cboFullEnumLevel) {
@@ -1521,9 +1530,9 @@ public class JoinNode {
if (!joinEnum.forceJoinOrderMode || level <= joinEnum.cboFullEnumLevel) {
buildBroadcastHashJoinPlan(rightPlan, leftPlan, hashJoinExpr, null, outerJoin);
}
- buildNLJoinPlan(leftPlan, rightPlan, nestedLoopJoinExpr, null, outerJoin);
+ buildNLJoinPlan(leftPlan, rightPlan, nestedLoopJoinExpr, null, outerJoin, indexProvider);
if (!joinEnum.forceJoinOrderMode || level <= joinEnum.cboFullEnumLevel) {
- buildNLJoinPlan(rightPlan, leftPlan, nestedLoopJoinExpr, null, outerJoin);
+ buildNLJoinPlan(rightPlan, leftPlan, nestedLoopJoinExpr, null, outerJoin, indexProvider);
}
buildCPJoinPlan(leftPlan, rightPlan, hashJoinExpr, nestedLoopJoinExpr, outerJoin);
if (!joinEnum.forceJoinOrderMode || level <= joinEnum.cboFullEnumLevel) {
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 47e5c6d277..deac2feff8 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
@@ -223,7 +223,7 @@ public class Stats {
LogicalVariable var;
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
+ // have to see if there are other alternatives later
leafInput = joinEnum.leafInputs.get(idx2 - 1);
var = exprUsedVars.get(1);
} else if (unnestOp2) {
@@ -277,6 +277,9 @@ public class Stats {
AbstractFunctionCallExpression joinExpr, JoinOperator join) throws AlgebricksException {
AbstractBinaryJoinOperator abjoin = join.getAbstractJoinOp();
Pair<ILogicalOperator, Double> leftOutput = replaceDataSourceWithSample(left, index1, joinExpr);
+ ILogicalOperator originalLeft, originalRight;
+ originalLeft = abjoin.getInputs().get(0).getValue();
+ originalRight = abjoin.getInputs().get(1).getValue();
abjoin.getInputs().get(0).setValue(leftOutput.getFirst());
Pair<ILogicalOperator, Double> rightOutput = replaceDataSourceWithSample(right, index2, joinExpr);
abjoin.getInputs().get(1).setValue(rightOutput.getFirst());
@@ -284,6 +287,10 @@ public class Stats {
List<List<IAObject>> result = runSamplingQuery(optCtx, abjoin);
double estCardSample = findPredicateCardinality(result, false);
double sel = estCardSample / leftOutput.getSecond() / rightOutput.getSecond();
+
+ abjoin.getInputs().get(0).setValue(originalLeft);
+ abjoin.getInputs().get(1).setValue(originalRight);
+
return sel;
}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AbstractAdvisorPlanNode.java
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AbstractAdvisorPlanNode.java
index 07a80349a7..23165e1d45 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AbstractAdvisorPlanNode.java
@@ -16,15 +16,23 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+import java.util.List;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+public abstract class AbstractAdvisorPlanNode {
+ protected AbstractAdvisorPlanNode(PlanNodeType planNodeType) {
+ this.planNodeType = planNodeType;
+ }
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
+ enum PlanNodeType {
+ SCAN,
+ JOIN
+ }
+
+ private final PlanNodeType planNodeType;
+
+ public abstract List<AdvisorScanPlanNode> getLeafs();
+
+ public abstract List<AdvisorJoinPlanNode> getJoins();
}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdviseIndexRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdviseIndexRule.java
new file mode 100644
index 0000000000..9a7fbdd53e
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdviseIndexRule.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+import org.apache.asterix.common.config.DatasetConfig;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.metadata.declared.IIndexProvider;
+import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.optimizer.rules.am.AccessMethodJobGenParams;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import org.apache.hyracks.algebricks.core.algebra.expressions.UnnestingFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractUnnestMapOperator;
+import org.apache.hyracks.algebricks.core.rewriter.base.IAlgebraicRewriteRule;
+
+// This rule executes after the CBO rule collections have run.
+// By this point, the CBO should have generated a plan that includes fake indexes.
+// This rule runs just once, is responsible for collecting and parsing the plan,
+// inspecting each operator, identifying index scan operators,
+// parses each operator to identify index scans, and adds the index details into the index advisor result.
+
+//distribute result [$$16]
+// project ([$$16])
+// assign [$$16] <- [{"A": $$A}]
+// select (eq($$18, 1))
+// assign [$$18] <- [$$A.getField("b")]
+// unnest-map [$$17, $$A] <- index-search("A", 0, "Default", "test", "A", false, false, 1, $$22, 1, $$22, true, true, true)
+// order (ASC, $$22) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+// select (eq($$21, 1))
+// unnest-map [$$21, $$22] <- index-search("fake_index_4b4f5c05-f666-4ba2-912e-1a580de50542", 0, "Default", "test", "A", false, false, 1, $$19, 1, $$20, true, true, true)
+// assign [$$19, $$20] <- [1, 1]
+// empty-tuple-source
+
+// This rule looks at unnest-map [$$21, $$22] <- index-search("fake_index_4b4f5c05-f666-4ba2-912e-1a580de50542", 0, "Default", "test", "A", false, false, 1, $$19, 1, $$20, true, true, true)
+// and extracts the index name field names from the fake index provider.
+
+public class AdviseIndexRule implements IAlgebraicRewriteRule {
+ boolean applied = false;
+
+ public AdviseIndexRule() {
+
+ }
+
+ @Override
+ public boolean rewritePost(Mutable<ILogicalOperator> opRef, IOptimizationContext context) {
+ return false;
+ }
+
+ @Override
+ public boolean rewritePre(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+ throws AlgebricksException {
+ if (applied) {
+ return false;
+ }
+ applied = true;
+
+ if (!context.getIndexAdvisor().getAdvise()) {
+ return false;
+ }
+
+ FakeIndexProvider fakeIndexProvider = (FakeIndexProvider) context.getIndexAdvisor().getFakeIndexProvider();
+ IIndexProvider actualIndexProvider = (IIndexProvider) context.getMetadataProvider();
+ visit(opRef, fakeIndexProvider, actualIndexProvider, context.getIndexAdvisor());
+
+ return true;
+
+ }
+
+ void visit(Mutable<ILogicalOperator> opRef, IIndexProvider fakeIndexProvider, IIndexProvider actualIndexProvider,
+ IndexAdvisor indexAdvisor) throws AlgebricksException {
+
+ ILogicalOperator op = opRef.getValue();
+
+ for (Mutable<ILogicalOperator> input : op.getInputs()) {
+ visit(input, fakeIndexProvider, actualIndexProvider, indexAdvisor);
+ }
+
+ if (op.getOperatorTag() == LogicalOperatorTag.UNNEST_MAP
+ || op.getOperatorTag() == LogicalOperatorTag.LEFT_OUTER_UNNEST_MAP) {
+ AbstractUnnestMapOperator unnestMapOp = (AbstractUnnestMapOperator) op;
+ ILogicalExpression expr = unnestMapOp.getExpressionRef().getValue();
+ if (!(expr instanceof UnnestingFunctionCallExpression unnestExpr)) {
+ return;
+ }
+
+ AccessMethodJobGenParams jobGenParams = new AccessMethodJobGenParams();
+ jobGenParams.readFromFuncArgs(unnestExpr.getArguments());
+ if (jobGenParams.isPrimaryIndex()) {
+ return;
+ }
+ if (jobGenParams.getIndexType() != DatasetConfig.IndexType.BTREE) {
+ return;
+ }
+
+ String indexName = jobGenParams.getIndexName();
+ String databaseName = jobGenParams.getDatabaseName();
+ DataverseName dataverse = jobGenParams.getDataverseName();
+ String datasetName = jobGenParams.getDatasetName();
+
+ Index fakeIndex = fakeIndexProvider.getIndex(databaseName, dataverse, datasetName, indexName);
+ Index actualIndex = lookupIndex(databaseName, dataverse, datasetName,
+ ((Index.ValueIndexDetails) fakeIndex.getIndexDetails()).getKeyFieldNames(), actualIndexProvider);
+
+ if (actualIndex != null
+ && actualIndex.getIndexDetails() instanceof Index.ValueIndexDetails valueIndexDetails) {
+ indexAdvisor.addPresentAdvise(actualIndex.getIndexName(), valueIndexDetails.getKeyFieldNames(),
+ databaseName, dataverse.getCanonicalForm(), datasetName);
+ return;
+ }
+
+ indexAdvisor.addRecommendedAdvise(
+ getIndexNameClause(((Index.ValueIndexDetails) fakeIndex.getIndexDetails()).getKeyFieldNames()),
+ ((Index.ValueIndexDetails) fakeIndex.getIndexDetails()).getKeyFieldNames(), databaseName,
+ dataverse.getCanonicalForm(), datasetName);
+
+ }
+
+ }
+
+ private static Index lookupIndex(String databaseName, DataverseName dataverseName, String datasetName,
+ List<List<String>> fieldsNames, IIndexProvider indexProvider) throws AlgebricksException {
+ return indexProvider.getDatasetIndexes(databaseName, dataverseName, datasetName).stream()
+ .filter(index -> index.getIndexDetails() instanceof Index.ValueIndexDetails)
+ .filter(index -> (((Index.ValueIndexDetails) index.getIndexDetails()).getKeyFieldNames()
+ .equals(fieldsNames)))
+ .filter(index -> !index.isEnforced()).findFirst().orElse(null);
+ }
+
+ public static String getIndexNameClause(List<List<String>> fields) {
+ return "idx_" + fields.stream().map(field -> String.join("_", field)).collect(Collectors.joining("_"))
+ .replaceAll(" ", "");
+ }
+
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorConditionParser.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorConditionParser.java
new file mode 100644
index 0000000000..a86b1b5df2
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorConditionParser.java
@@ -0,0 +1,229 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.asterix.metadata.utils.PushdownUtil;
+import org.apache.asterix.om.functions.BuiltinFunctions;
+import org.apache.asterix.optimizer.rules.am.BTreeAccessMethod;
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalExpression;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalExpressionTag;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.expressions.AbstractFunctionCallExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import org.apache.hyracks.algebricks.core.algebra.expressions.IVariableTypeEnvironment;
+import org.apache.hyracks.algebricks.core.algebra.expressions.VariableReferenceExpression;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractLogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.SelectOperator;
+import org.apache.hyracks.algebricks.core.algebra.util.OperatorManipulationUtil;
+
+public class AdvisorConditionParser {
+
+ public static ScanFilter parseScanNode(ILogicalOperator op, IOptimizationContext context)
+ throws AlgebricksException {
+
+ List<Mutable<ILogicalExpression>> filterExprs = new ArrayList<>();
+ IVariableTypeEnvironment typeEnv = PushdownUtil.getTypeEnv(op, context);
+ ILogicalOperator tempOp = op;
+ do {
+ if (tempOp.getOperatorTag() == LogicalOperatorTag.SELECT) {
+ SelectOperator selectOp = (SelectOperator) tempOp;
+ ILogicalExpression condition = selectOp.getCondition().getValue();
+ List<Mutable<ILogicalExpression>> conjs = new ArrayList<>();
+ if (condition.splitIntoConjuncts(conjs)) {
+ filterExprs.addAll(conjs);
+ } else {
+ filterExprs.add(selectOp.getCondition());
+ }
+ }
+ tempOp = tempOp.getInputs().getFirst().getValue();
+ } while (tempOp.hasInputs());
+
+ filterExprs = OperatorManipulationUtil.cloneExpressions(filterExprs);
+
+ filterExprs.removeIf(expr -> !(expr.getValue() instanceof AbstractFunctionCallExpression));
+
+ tempOp = op;
+ do {
+ if (tempOp.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
+ replaceExprsWithAssign((AssignOperator) tempOp, filterExprs);
+ }
+ tempOp = tempOp.getInputs().getFirst().getValue();
+ } while (tempOp.hasInputs());
+
+ List<ScanFilterCondition> filterConditions = new ArrayList<>();
+
+ for (Mutable<ILogicalExpression> filterExpr : filterExprs) {
+ ScanFilterCondition filterCondition = parseCondition(filterExpr.getValue(), typeEnv);
+ if (filterCondition != null) {
+ filterConditions.add(filterCondition);
+ }
+ }
+
+ return new ScanFilter(filterConditions);
+ }
+
+ private static ScanFilterCondition parseCondition(ILogicalExpression logicalExpression,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+ if (!(logicalExpression instanceof AbstractFunctionCallExpression expr)) {
+ return null;
+ }
+
+ FunctionIdentifier fi = expr.getFunctionIdentifier();
+
+ if (!BTreeAccessMethod.INSTANCE.getOptimizableFunctions().contains(new Pair<>(fi, false))) {
+ return null;
+ }
+
+ ConstantExpression constantExpression = null;
+ Pair<LogicalVariable, List<String>> accessPath = null;
+
+ if (expr.getArguments().get(1).getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
+ constantExpression = (ConstantExpression) expr.getArguments().get(1).getValue();
+ accessPath = parseAccessPath(expr.getArguments().get(0).getValue(), typeEnv);
+ } else if (expr.getArguments().get(0).getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
+ constantExpression = (ConstantExpression) expr.getArguments().get(0).getValue();
+ accessPath = parseAccessPath(expr.getArguments().get(1).getValue(), typeEnv);
+ }
+ if (accessPath == null) {
+ return null;
+ }
+
+ return new ScanFilterCondition(fi, accessPath.getSecond(), constantExpression);
+ }
+
+ private static Pair<LogicalVariable, List<String>> parseAccessPath(ILogicalExpression expr,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+ List<String> fieldNames = new LinkedList<>();
+ while (expr.getExpressionTag() != LogicalExpressionTag.VARIABLE) {
+ if (expr.getExpressionTag() != LogicalExpressionTag.FUNCTION_CALL) {
+ return null;
+ }
+ AbstractFunctionCallExpression functionCallExpr = (AbstractFunctionCallExpression) expr;
+ FunctionIdentifier fi = functionCallExpr.getFunctionIdentifier();
+ if (fi != BuiltinFunctions.FIELD_ACCESS_BY_NAME && fi != BuiltinFunctions.FIELD_ACCESS_BY_INDEX) {
+ return null;
+ }
+ String fieldName = PushdownUtil.getFieldName(functionCallExpr, typeEnv);
+ fieldNames.addFirst(fieldName);
+
+ expr = functionCallExpr.getArguments().getFirst().getValue();
+ }
+
+ VariableReferenceExpression varRef = (VariableReferenceExpression) expr;
+ LogicalVariable var = varRef.getVariableReference();
+ return new Pair<>(var, fieldNames);
+ }
+
+ public static JoinFilter parseJoinNode(AbstractBinaryJoinOperator joinOp, IOptimizationContext context)
+ throws AlgebricksException {
+ List<Mutable<ILogicalExpression>> joinExprs = new ArrayList<>();
+ IVariableTypeEnvironment typeEnv = PushdownUtil.getTypeEnv(joinOp, context);
+
+ ILogicalExpression joinExpression = joinOp.getCondition().getValue();
+ List<Mutable<ILogicalExpression>> conjs = new ArrayList<>();
+ if (joinExpression.splitIntoConjuncts(conjs)) {
+ joinExprs.addAll(conjs);
+ } else {
+ joinExprs.add(joinOp.getCondition());
+ }
+ joinExprs = OperatorManipulationUtil.cloneExpressions(joinExprs);
+ traverseAndReplace(joinOp, joinExprs);
+
+ List<JoinFilterCondition> joinConditions = new ArrayList<>();
+
+ for (Mutable<ILogicalExpression> joinExpr : joinExprs) {
+ JoinFilterCondition joinCondition = parseJoinCondition(joinExpr.getValue(), typeEnv);
+ if (joinCondition != null) {
+ joinConditions.add(joinCondition);
+ }
+ }
+
+ return new JoinFilter(joinConditions);
+ }
+
+ private static void traverseAndReplace(AbstractLogicalOperator op, List<Mutable<ILogicalExpression>> exprs) {
+
+ if (op.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
+ replaceExprsWithAssign((AssignOperator) op, exprs);
+ }
+
+ for (Mutable<ILogicalOperator> input : op.getInputs()) {
+ traverseAndReplace((AbstractLogicalOperator) input.getValue(), exprs);
+ }
+
+ }
+
+ public static void replaceExprsWithAssign(AssignOperator assignOp, List<Mutable<ILogicalExpression>> exprs) {
+ for (Mutable<ILogicalExpression> filterExpr : exprs) {
+ if (filterExpr.getValue().getExpressionTag() == LogicalExpressionTag.CONSTANT) {
+ continue;
+ }
+ for (int i = 0; i < assignOp.getVariables().size(); i++) {
+ OperatorManipulationUtil.replaceVarWithExpr((AbstractFunctionCallExpression) filterExpr.getValue(),
+ assignOp.getVariables().get(i), assignOp.getExpressions().get(i).getValue());
+ }
+ }
+ }
+
+ public static JoinFilterCondition parseJoinCondition(ILogicalExpression logicalExpression,
+ IVariableTypeEnvironment typeEnv) throws AlgebricksException {
+
+ if (!(logicalExpression instanceof AbstractFunctionCallExpression expr)) {
+ return null;
+ }
+
+ FunctionIdentifier fi = expr.getFunctionIdentifier();
+
+ if (!BTreeAccessMethod.INSTANCE.getOptimizableFunctions().contains(new Pair<>(fi, false))) {
+ return null;
+ }
+
+ if (expr.getArguments().size() != 2) {
+ return null;
+ }
+
+ ILogicalExpression lhs = expr.getArguments().get(0).getValue();
+ ILogicalExpression rhs = expr.getArguments().get(1).getValue();
+
+ Pair<LogicalVariable, List<String>> lhsAccessPath = parseAccessPath(lhs, typeEnv);
+ if (lhsAccessPath == null) {
+ return null;
+ }
+ Pair<LogicalVariable, List<String>> rhsAccessPath = parseAccessPath(rhs, typeEnv);
+ if (rhsAccessPath == null) {
+ return null;
+ }
+ return new JoinFilterCondition(fi, lhsAccessPath.getFirst(), lhsAccessPath.getSecond(),
+ rhsAccessPath.getFirst(), rhsAccessPath.getSecond());
+ }
+
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorJoinPlanNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorJoinPlanNode.java
new file mode 100644
index 0000000000..44f7855aa1
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorJoinPlanNode.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
+
+public class AdvisorJoinPlanNode extends AbstractAdvisorPlanNode {
+ private final AbstractAdvisorPlanNode left;
+ private final AbstractAdvisorPlanNode right;
+ private final JoinFilter joinCondition;
+
+ public AdvisorJoinPlanNode(AbstractAdvisorPlanNode left, AbstractAdvisorPlanNode right,
+ AbstractBinaryJoinOperator joinOp, IOptimizationContext context) throws AlgebricksException {
+ super(PlanNodeType.JOIN);
+ this.left = left;
+ this.right = right;
+ this.joinCondition = AdvisorConditionParser.parseJoinNode(joinOp, context);
+ }
+
+ @Override
+ public List<AdvisorScanPlanNode> getLeafs() {
+ List<AdvisorScanPlanNode> leafs = new ArrayList<>();
+ leafs.addAll(left.getLeafs());
+ leafs.addAll(right.getLeafs());
+ return leafs;
+ }
+
+ @Override
+ public List<AdvisorJoinPlanNode> getJoins() {
+ List<AdvisorJoinPlanNode> joins = new ArrayList<>();
+ joins.add(this);
+ joins.addAll(left.getJoins());
+ joins.addAll(right.getJoins());
+ return joins;
+ }
+
+ public JoinFilter getJoinCondition() {
+ return joinCondition;
+ }
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorPlanParser.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorPlanParser.java
new file mode 100644
index 0000000000..8b341bbecd
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorPlanParser.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import static org.apache.asterix.optimizer.rules.cbo.EnumerateJoinsRule.containsLeafInputOnly;
+import static org.apache.asterix.optimizer.rules.cbo.EnumerateJoinsRule.joinClause;
+import static org.apache.asterix.optimizer.rules.cbo.EnumerateJoinsRule.numVarRefExprs;
+import static org.apache.asterix.optimizer.rules.cbo.EnumerateJoinsRule.skipPastAssigns;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.mutable.Mutable;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AbstractBinaryJoinOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.AssignOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.EmptyTupleSourceOperator;
+
+public class AdvisorPlanParser {
+ public static CBOPlanStateTree getCBOPlanState(Mutable<ILogicalOperator> opRef, IOptimizationContext context)
+ throws AlgebricksException {
+ Map<Mutable<ILogicalOperator>, Boolean> visited = new HashMap<>();
+ return visit(opRef, visited, context);
+ }
+
+ private static CBOPlanStateTree visit(Mutable<ILogicalOperator> opRef,
+ Map<Mutable<ILogicalOperator>, Boolean> visited, IOptimizationContext context) throws AlgebricksException {
+ CBOPlanStateTree planStateTree = runGetOps(opRef, visited, context);
+ if (planStateTree != null) {
+ return planStateTree;
+ }
+ for (Mutable<ILogicalOperator> childOpRef : opRef.getValue().getInputs()) {
+ planStateTree = visit(childOpRef, visited, context);
+
+ if (planStateTree != null) {
+ return planStateTree;
+ }
+ }
+ return null;
+ }
+
+ private static CBOPlanStateTree runGetOps(Mutable<ILogicalOperator> opRef,
+ Map<Mutable<ILogicalOperator>, Boolean> visited, IOptimizationContext context) throws AlgebricksException {
+ if (visited.containsKey(opRef)) {
+ return null;
+ }
+ if (!joinClause(opRef.getValue())
+ && opRef.getValue().getOperatorTag() != LogicalOperatorTag.DISTRIBUTE_RESULT) {
+ return null;
+ }
+ AbstractAdvisorPlanNode planNode = getJoinOpsAndLeafInputs(opRef.getValue(), context);
+ if (planNode == null) {
+ return null;
+ }
+ return new CBOPlanStateTree(planNode);
+ }
+
+ private static AbstractAdvisorPlanNode getJoinOpsAndLeafInputs(ILogicalOperator op, IOptimizationContext context)
+ throws AlgebricksException {
+ if (onlyAssigns(op)) {
+ AbstractBinaryJoinOperator skipAssignOp = (AbstractBinaryJoinOperator) skipPastAssigns(op);
+ AbstractAdvisorPlanNode leftPlanNode =
+ getJoinOpsAndLeafInputs(skipAssignOp.getInputs().get(0).getValue(), context);
+ AbstractAdvisorPlanNode rightPlanNode =
+ getJoinOpsAndLeafInputs(skipAssignOp.getInputs().get(1).getValue(), context);
+ if (leftPlanNode == null || rightPlanNode == null) {
+ return null;
+ }
+ return new AdvisorJoinPlanNode(leftPlanNode, rightPlanNode, skipAssignOp, context);
+ } else {
+ if (op.getOperatorTag() == LogicalOperatorTag.GROUP) {
+ return null;
+ }
+ Pair<EmptyTupleSourceOperator, DataSourceScanOperator> etsDataSource = containsLeafInputOnly(op);
+ if (etsDataSource == null || etsDataSource.second == null) {
+ return null;
+ }
+ return new AdvisorScanPlanNode(op, context);
+ }
+ }
+
+ private static boolean onlyAssigns(ILogicalOperator op) {
+ while (op.getOperatorTag() == LogicalOperatorTag.ASSIGN) {
+ AssignOperator aOp = (AssignOperator) op;
+ int count = numVarRefExprs(aOp);
+ if (count > 1) {
+ return false;
+ }
+ op = op.getInputs().get(0).getValue();
+ }
+ return (joinClause(op));
+ }
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorScanPlanNode.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorScanPlanNode.java
new file mode 100644
index 0000000000..f4a15d8b99
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/AdvisorScanPlanNode.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
+import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalOperatorTag;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
+
+public class AdvisorScanPlanNode extends AbstractAdvisorPlanNode {
+ private ILogicalOperator op;
+ private final DataSourceScanOperator scanOperator;
+ private final ScanFilter filter;
+
+ public AdvisorScanPlanNode(ILogicalOperator op, IOptimizationContext context) throws AlgebricksException {
+ super(PlanNodeType.SCAN);
+ this.op = op;
+ this.scanOperator = findDatascanOperator(op);
+ filter = AdvisorConditionParser.parseScanNode(op, context);
+ }
+
+ private DataSourceScanOperator findDatascanOperator(ILogicalOperator op) {
+ while (op.getOperatorTag() != LogicalOperatorTag.DATASOURCESCAN) {
+ op = op.getInputs().get(0).getValue();
+ }
+ return (DataSourceScanOperator) op;
+ }
+
+ public DataSourceScanOperator getScanOperator() {
+ return scanOperator;
+ }
+
+ @Override
+ public List<AdvisorScanPlanNode> getLeafs() {
+ return Collections.singletonList(this);
+ }
+
+ @Override
+ public List<AdvisorJoinPlanNode> getJoins() {
+ return Collections.emptyList();
+ }
+
+ public ScanFilter getFilter() {
+ return filter;
+ }
+
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/CBOPlanStateTree.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/CBOPlanStateTree.java
new file mode 100644
index 0000000000..62449167cd
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/CBOPlanStateTree.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
+
+public class CBOPlanStateTree {
+ private final AbstractAdvisorPlanNode cboPlanNode;
+ private final Map<LogicalVariable, DataSourceScanOperator> dataSourceScanVariableMap;
+
+ public CBOPlanStateTree(AbstractAdvisorPlanNode cboPlanNode) {
+ this.cboPlanNode = cboPlanNode;
+ dataSourceScanVariableMap = new HashMap<>();
+ for (AdvisorScanPlanNode scanNode : cboPlanNode.getLeafs()) {
+ DataSourceScanOperator scanOperator = scanNode.getScanOperator();
+ for (LogicalVariable variable : scanOperator.getVariables()) {
+ dataSourceScanVariableMap.put(variable, scanOperator);
+ }
+ }
+ }
+
+ public AbstractAdvisorPlanNode getCboPlanNode() {
+ return cboPlanNode;
+ }
+
+ public Map<LogicalVariable, DataSourceScanOperator> getDataSourceScanVariableMap() {
+ return dataSourceScanVariableMap;
+ }
+
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/FakeIndex.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/FakeIndex.java
new file mode 100644
index 0000000000..b7fd1a7d5c
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/FakeIndex.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.asterix.common.config.DatasetConfig;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.common.metadata.MetadataUtil;
+import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.metadata.utils.Creator;
+import org.apache.asterix.om.types.BuiltinType;
+import org.apache.hyracks.util.OptionalBoolean;
+
+public class FakeIndex extends Index {
+ private static final long serialVersionUID = 8100544760363679761L;
+
+ public FakeIndex(String databaseName, DataverseName dataverseName, String datasetName, String indexName,
+ List<List<String>> fieldNames, boolean isPrimary) {
+ super(databaseName, dataverseName, datasetName, indexName, DatasetConfig.IndexType.BTREE,
+ new ValueIndexDetails(fieldNames, Collections.nCopies(fieldNames.size(), 0),
+ Collections.nCopies(fieldNames.size(), BuiltinType.ANY), false, OptionalBoolean.FALSE(),
+ OptionalBoolean.empty(), null, null, null)
+
+ , false, isPrimary, MetadataUtil.PENDING_NO_OP, Creator.DEFAULT_CREATOR);
+ }
+
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/FakeIndexProvider.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/FakeIndexProvider.java
new file mode 100644
index 0000000000..ee487dd146
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/FakeIndexProvider.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import static java.util.UUID.randomUUID;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.asterix.common.config.DatasetConfig;
+import org.apache.asterix.common.metadata.DatasetFullyQualifiedName;
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.metadata.declared.DataSourceId;
+import org.apache.asterix.metadata.declared.DatasetDataSource;
+import org.apache.asterix.metadata.declared.IIndexProvider;
+import org.apache.asterix.metadata.entities.Index;
+import org.apache.asterix.metadata.entities.InternalDatasetDetails;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
+import org.apache.hyracks.algebricks.common.utils.Pair;
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.operators.logical.DataSourceScanOperator;
+
+public class FakeIndexProvider implements IIndexProvider {
+
+ private final Map<DatasetFullyQualifiedName, Map<String, Index>> filterIndexesMap;
+ private final IIndexEnumerator singleDataSourceIndexEnumerator = IIndexEnumerator.alphabeticEnumerator();
+ private final IIndexEnumerator joinIndexEnumerator = IIndexEnumerator.alphabeticEnumerator();
+
+ public FakeIndexProvider(CBOPlanStateTree planStateTree) {
+ filterIndexesMap = new HashMap<>();
+ if (planStateTree == null || planStateTree.getCboPlanNode() == null) {
+ return;
+ }
+
+ addSingleDataSourceIndexes(planStateTree.getCboPlanNode().getLeafs());
+ addJoinIndexes(planStateTree.getCboPlanNode().getJoins(), planStateTree.getDataSourceScanVariableMap());
+ }
+
+ private void addSingleDataSourceIndexes(List<AdvisorScanPlanNode> scanPlanNodes) {
+ Map<DatasetFullyQualifiedName, Pair<DataSourceScanOperator, Set<List<String>>>> singleDataSourceFieldNamesMap =
+ new HashMap<>();
+ for (AdvisorScanPlanNode scanPlanNode : scanPlanNodes) {
+ DataSourceScanOperator scanOperator = scanPlanNode.getScanOperator();
+
+ if (!(scanOperator.getDataSource() instanceof DatasetDataSource dataSource)) {
+ continue;
+ }
+ DatasetFullyQualifiedName fullyQualifiedName = dataSource.getDataset().getDatasetFullyQualifiedName();
+
+ ScanFilter filter = scanPlanNode.getFilter();
+ List<ScanFilterCondition> filterConditions = filter.filterConditions();
+ HashSet<List<String>> datasetFieldNames = new HashSet<>();
+ for (ScanFilterCondition filterCondition : filterConditions) {
+ datasetFieldNames.add(filterCondition.getLhsFieldAccessPath());
+ }
+ singleDataSourceFieldNamesMap.put(fullyQualifiedName, new Pair<>(scanOperator, datasetFieldNames));
+
+ }
+ for (Map.Entry<DatasetFullyQualifiedName, Pair<DataSourceScanOperator, Set<List<String>>>> entry : singleDataSourceFieldNamesMap
+ .entrySet()) {
+ DatasetFullyQualifiedName qualifiedName = entry.getKey();
+ Set<List<String>> fieldNames = entry.getValue().getSecond();
+ DataSourceScanOperator scanOperator = entry.getValue().getFirst();
+
+ if (((DatasetDataSource) scanOperator.getDataSource()).getDataset().getDatasetDetails()
+ .getDatasetType() != DatasetConfig.DatasetType.INTERNAL) {
+ continue;
+ }
+
+ List<List<String>> primaryKeys =
+ ((InternalDatasetDetails) ((DatasetDataSource) scanOperator.getDataSource()).getDataset()
+ .getDatasetDetails()).getPrimaryKey();
+
+ Map<String, Index> datasetIndexes = new HashMap<>();
+ filterIndexesMap.put(qualifiedName, datasetIndexes);
+
+ String primaryKeyName = ((DataSourceId) scanOperator.getDataSource().getId()).getDatasourceName();
+
+ FakeIndex primIndex = new FakeIndex(qualifiedName.getDatabaseName(), qualifiedName.getDataverseName(),
+ qualifiedName.getDatasetName(), primaryKeyName, primaryKeys, true);
+ datasetIndexes.put(primaryKeyName, primIndex);
+
+ if (fieldNames.isEmpty()) {
+ continue;
+ }
+
+ singleDataSourceIndexEnumerator.init(fieldNames);
+ Iterator<List<List<String>>> itr = singleDataSourceIndexEnumerator.getIterator();
+
+ while (itr.hasNext()) {
+ String indexName = "fake_index_" + randomUUID();
+ FakeIndex fakeIndex = new FakeIndex(qualifiedName.getDatabaseName(), qualifiedName.getDataverseName(),
+ qualifiedName.getDatasetName(), indexName, itr.next(), false);
+ datasetIndexes.put(indexName, fakeIndex);
+ }
+ }
+ }
+
+ private void addJoinIndexes(List<AdvisorJoinPlanNode> joinPlanNodes,
+ Map<LogicalVariable, DataSourceScanOperator> dataSourceScanVariableMap) {
+ Map<DatasetFullyQualifiedName, Set<List<String>>> joinDataSourceFieldNamesMap = new HashMap<>();
+ for (AdvisorJoinPlanNode joinPlanNode : joinPlanNodes) {
+ for (JoinFilterCondition filterCondition : joinPlanNode.getJoinCondition().joinFilterConditions()) {
+ addOperandToMap(filterCondition.getLhsVar(), filterCondition.getLhsFields(),
+ joinDataSourceFieldNamesMap, dataSourceScanVariableMap);
+ addOperandToMap(filterCondition.getRhsVar(), filterCondition.getRhsFields(),
+ joinDataSourceFieldNamesMap, dataSourceScanVariableMap);
+ }
+
+ }
+ for (Map.Entry<DatasetFullyQualifiedName, Set<List<String>>> entry : joinDataSourceFieldNamesMap.entrySet()) {
+ DatasetFullyQualifiedName qualifiedName = entry.getKey();
+ Set<List<String>> fieldNames = entry.getValue();
+
+ joinIndexEnumerator.init(fieldNames);
+ Iterator<List<List<String>>> itr = joinIndexEnumerator.getIterator();
+ Map<String, Index> indexes = filterIndexesMap.get(qualifiedName);
+
+ while (itr.hasNext()) {
+ String indexName = "fake_join_index_" + randomUUID();
+ FakeIndex fakeIndex = new FakeIndex(qualifiedName.getDatabaseName(), qualifiedName.getDataverseName(),
+ qualifiedName.getDatasetName(), indexName, itr.next(), false);
+ indexes.put(indexName, fakeIndex);
+ }
+
+ }
+ }
+
+ private void addOperandToMap(LogicalVariable var, List<String> fields,
+ Map<DatasetFullyQualifiedName, Set<List<String>>> joinDataSourceFieldNamesMap,
+ Map<LogicalVariable, DataSourceScanOperator> dataSourceScanVariableMap) {
+ DataSourceScanOperator op = dataSourceScanVariableMap.get(var);
+ if (op == null) {
+ return;
+ }
+ if (!(op.getDataSource() instanceof DatasetDataSource dataSource)) {
+ return;
+ }
+ DatasetFullyQualifiedName qualifiedName = dataSource.getDataset().getDatasetFullyQualifiedName();
+ joinDataSourceFieldNamesMap.computeIfAbsent(qualifiedName, k -> new HashSet<>()).add(fields);
+ }
+
+ @Override
+ public Index getIndex(String database, DataverseName dataverseName, String datasetName, String indexName)
+ throws AlgebricksException {
+ return filterIndexesMap.get(new DatasetFullyQualifiedName(database, dataverseName, datasetName)).get(indexName);
+ }
+
+ @Override
+ public List<Index> getDatasetIndexes(String database, DataverseName dataverseName, String datasetName)
+ throws AlgebricksException {
+ return filterIndexesMap.get(new DatasetFullyQualifiedName(database, dataverseName, datasetName)).values()
+ .stream().toList();
+ }
+
+}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/IIndexEnumerator.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/IIndexEnumerator.java
new file mode 100644
index 0000000000..d554e838e7
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/IIndexEnumerator.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.collections4.iterators.PermutationIterator;
+
+public interface IIndexEnumerator {
+
+ Iterator<List<List<String>>> getIterator();
+
+ void init(Collection<List<String>> fieldNames);
+
+ static IIndexEnumerator allFieldsEnumerator() {
+
+ return new IIndexEnumerator() {
+ private PermutationIterator<List<String>> permutationIterator;
+
+ @Override
+ public Iterator<List<List<String>>> getIterator() {
+ return permutationIterator;
+ }
+
+ @Override
+ public void init(Collection<List<String>> fieldNames) {
+ this.permutationIterator = new PermutationIterator<>(new ArrayList<>(fieldNames));
+ }
+ };
+ }
+
+ static IIndexEnumerator alphabeticEnumerator() {
+ return new IIndexEnumerator() {
+ private List<List<String>> listOfAllFields;
+
+ @Override
+ public Iterator<List<List<String>>> getIterator() {
+ ArrayList<List<List<String>>> list = new ArrayList<>();
+ list.add(listOfAllFields);
+ return list.iterator();
+ }
+
+ @Override
+ public void init(Collection<List<String>> fieldNames) {
+ this.listOfAllFields = new ArrayList<>(fieldNames);
+ listOfAllFields.sort((list1, list2) -> {
+ int minSize = Math.min(list1.size(), list2.size());
+ for (int i = 0; i < minSize; i++) {
+ int comparison = list1.get(i).compareTo(list2.get(i));
+ if (comparison != 0) {
+ return comparison;
+ }
+ }
+ return Integer.compare(list1.size(), list2.size());
+ });
+
+ }
+ };
+ }
+
+}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/JoinFilter.java
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/JoinFilter.java
index 07a80349a7..e3d4af6f24 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/JoinFilter.java
@@ -16,15 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+import java.util.List;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
-
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+public record JoinFilter(List<JoinFilterCondition>joinFilterConditions){}
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/JoinFilterCondition.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/JoinFilterCondition.java
new file mode 100644
index 0000000000..bca51ee54b
--- /dev/null
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/JoinFilterCondition.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
+
+import java.util.List;
+
+import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
+
+public class JoinFilterCondition {
+ private final FunctionIdentifier fi;
+ private final List<String> lhsFields;
+ private final List<String> rhsFields;
+ private final LogicalVariable lhsVar;
+ private final LogicalVariable rhsVar;
+
+ public JoinFilterCondition(FunctionIdentifier fi, LogicalVariable lhsVar, List<String> lhsFields,
+ LogicalVariable rhsVar, List<String> rhsFields) {
+ this.fi = fi;
+ this.lhsFields = lhsFields;
+ this.rhsFields = rhsFields;
+ this.lhsVar = lhsVar;
+ this.rhsVar = rhsVar;
+ }
+
+ public List<String> getLhsFields() {
+ return lhsFields;
+ }
+
+ public List<String> getRhsFields() {
+ return rhsFields;
+ }
+
+ public LogicalVariable getLhsVar() {
+ return lhsVar;
+ }
+
+ public LogicalVariable getRhsVar() {
+ return rhsVar;
+ }
+}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/ScanFilter.java
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/ScanFilter.java
index 07a80349a7..45535168a9 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/ScanFilter.java
@@ -16,15 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+import java.util.List;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+public record ScanFilter(List<ScanFilterCondition>filterConditions){
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/ScanFilterCondition.java
similarity index 52%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/ScanFilterCondition.java
index 07a80349a7..1036e9cd2f 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/indexadvisor/ScanFilterCondition.java
@@ -16,15 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
+package org.apache.asterix.optimizer.rules.cbo.indexadvisor;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+import java.util.List;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+import org.apache.hyracks.algebricks.core.algebra.expressions.ConstantExpression;
+import org.apache.hyracks.algebricks.core.algebra.functions.FunctionIdentifier;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
+public class ScanFilterCondition {
+ private final FunctionIdentifier fi;
+ private final List<String> lhsFieldAccessPath;
+ private final ConstantExpression rhs;
+
+ public ScanFilterCondition(FunctionIdentifier fi, List<String> lhsFieldAccessPath, ConstantExpression rhs) {
+ this.fi = fi;
+ this.lhsFieldAccessPath = lhsFieldAccessPath;
+ this.rhs = rhs;
+ }
+
+ public List<String> getLhsFieldAccessPath() {
+ return lhsFieldAccessPath;
+ }
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
index 511861849c..59e6dc2d09 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/common/APIFramework.java
@@ -18,6 +18,9 @@
*/
package org.apache.asterix.api.common;
+import static org.apache.asterix.compiler.provider.IRuleSetFactory.RuleSetKind.LOGICAL_ADVISOR;
+import static org.apache.asterix.compiler.provider.IRuleSetFactory.RuleSetKind.QUERY;
+
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
@@ -36,6 +39,7 @@ import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslator;
import org.apache.asterix.algebra.base.ILangExpressionToPlanTranslatorFactory;
import org.apache.asterix.api.http.server.ResultUtil;
import org.apache.asterix.app.result.fields.ExplainOnlyResultsPrinter;
+import org.apache.asterix.app.result.fields.IndexAdviseResultsPrinter;
import org.apache.asterix.app.result.fields.SignaturePrinter;
import org.apache.asterix.common.api.INodeJobTracker;
import org.apache.asterix.common.api.IResponsePrinter;
@@ -87,6 +91,7 @@ import org.apache.hyracks.algebricks.compiler.api.ICompiler;
import org.apache.hyracks.algebricks.compiler.api.ICompilerFactory;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
import org.apache.hyracks.algebricks.core.algebra.expressions.ExpressionRuntimeProvider;
import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
@@ -97,6 +102,7 @@ import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksStringBu
import org.apache.hyracks.algebricks.core.algebra.prettyprint.IPlanPrettyPrinter;
import org.apache.hyracks.algebricks.core.algebra.prettyprint.PlanPrettyPrinter;
import org.apache.hyracks.algebricks.core.rewriter.base.IOptimizationContextFactory;
+import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
import org.apache.hyracks.algebricks.core.rewriter.base.PhysicalOptimizationConfig;
import org.apache.hyracks.algebricks.core.utils.DotFormatGenerator;
import org.apache.hyracks.algebricks.data.IPrinterFactoryProvider;
@@ -180,12 +186,13 @@ public class APIFramework {
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
IConflictingTypeResolver conflictingTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector) {
+ AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector,
+ IndexAdvisor indexAdvisor) {
IPlanPrettyPrinter prettyPrinter = PlanPrettyPrinter.createStringPlanPrettyPrinter();
return new AsterixOptimizationContext(this, varCounter, expressionEvalSizeComputer,
mergeAggregationExpressionFactory, expressionTypeComputer, missableTypeComputer,
conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrinter,
- warningCollector);
+ warningCollector, indexAdvisor);
}
@Override
@@ -228,6 +235,7 @@ public class APIFramework {
final SourceLocation sourceLoc = query != null ? query.getSourceLocation()
: statement != null ? statement.getSourceLocation() : null;
final boolean isExplainOnly = isQuery && query.isExplain();
+ final boolean isAdviceOnly = isQuery && query.isAdvise();
SessionConfig conf = output.config();
if (isQuery && !conf.is(SessionConfig.FORMAT_ONLY_PHYSICAL_OPS)
@@ -261,6 +269,7 @@ public class APIFramework {
builder.setLogicalRewrites(() -> ruleSetFactory.getLogicalRewrites(ccAppContext));
builder.setLogicalRewritesByKind(kind -> ruleSetFactory.getLogicalRewrites(kind, ccAppContext));
builder.setPhysicalRewrites(() -> ruleSetFactory.getPhysicalRewrites(ccAppContext));
+ builder.setPhysicalRewritesByKind(kind -> ruleSetFactory.getPhysicalRewrites(kind, ccAppContext));
IDataFormat format = metadataProvider.getDataFormat();
ICompilerFactory compilerFactory = builder.create();
builder.setExpressionEvalSizeComputer(format.getExpressionEvalSizeComputer());
@@ -302,7 +311,10 @@ public class APIFramework {
builder.setTypeTraitProvider(format.getTypeTraitProvider());
builder.setNormalizedKeyComputerFactoryProvider(format.getNormalizedKeyComputerFactoryProvider());
- ICompiler compiler = compilerFactory.createCompiler(plan, metadataProvider, t.getVarCounter());
+ IndexAdvisor indexAdvisor = new IndexAdvisor(isAdviceOnly);
+ IRuleSetKind ruleSetKind = isAdviceOnly ? LOGICAL_ADVISOR : QUERY;
+ ICompiler compiler = compilerFactory.createCompiler(plan, metadataProvider, t.getVarCounter(), ruleSetKind,
+ indexAdvisor);
if (conf.isOptimize()) {
compiler.optimize();
if (conf.is(SessionConfig.OOB_OPTIMIZED_LOGICAL_PLAN) || isExplainOnly) {
@@ -313,7 +325,7 @@ public class APIFramework {
PlanPrettyPrinter.printPhysicalOps(plan, buf, 0, true);
output.out().write(buf.toString());
} else {
- if (isQuery || isLoad || isCopy) {
+ if ((isQuery || isLoad || isCopy) && !isAdviceOnly) {
generateOptimizedLogicalPlan(plan, output.config().getPlanFormat(), cboMode);
}
}
@@ -350,6 +362,12 @@ public class APIFramework {
JobEventListenerFactory jobEventListenerFactory =
new JobEventListenerFactory(txnId, metadataProvider.isWriteTransaction());
+
+ if (isAdviceOnly) {
+ printAdviseAsResult(metadataProvider, output, printer, indexAdvisor);
+ return null;
+ }
+
JobSpecification spec = compiler.createJob(ccAppContext, jobEventListenerFactory, runtimeFlags);
if (isQuery || isCopy) {
@@ -399,6 +417,18 @@ public class APIFramework {
}
}
+ private void printAdviseAsResult(MetadataProvider metadataProvider, SessionOutput output, IResponsePrinter printer,
+ IndexAdvisor advisor) throws AlgebricksException {
+
+ try {
+ printer.addResultPrinter(
+ new IndexAdviseResultsPrinter(metadataProvider.getApplicationContext(), advisor, output));
+ printer.printResults();
+ } catch (HyracksDataException e) {
+ throw new AlgebricksException(e);
+ }
+ }
+
private void printPlanAsResult(MetadataProvider metadataProvider, SessionOutput output, IResponsePrinter printer,
boolean printSignature) throws AlgebricksException {
try {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/IndexAdviseResultsPrinter.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/IndexAdviseResultsPrinter.java
new file mode 100644
index 0000000000..9e636ff332
--- /dev/null
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/result/fields/IndexAdviseResultsPrinter.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.asterix.app.result.fields;
+
+import java.io.PrintWriter;
+
+import org.apache.asterix.api.http.server.ResultUtil;
+import org.apache.asterix.common.api.IApplicationContext;
+import org.apache.asterix.common.api.IResponseFieldPrinter;
+import org.apache.asterix.translator.IStatementExecutor;
+import org.apache.asterix.translator.SessionConfig;
+import org.apache.asterix.translator.SessionOutput;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
+import org.apache.hyracks.api.exceptions.HyracksDataException;
+
+public class IndexAdviseResultsPrinter implements IResponseFieldPrinter {
+
+ private final IApplicationContext appCtx;
+ private final IndexAdvisor advisor;
+ private final SessionOutput sessionOutput;
+
+ public IndexAdviseResultsPrinter(IApplicationContext appCtx, IndexAdvisor advisor, SessionOutput sessionOutput) {
+ this.appCtx = appCtx;
+ this.advisor = advisor;
+ this.sessionOutput = sessionOutput;
+ }
+
+ @Override
+ public void print(PrintWriter pw) throws HyracksDataException {
+ boolean quoteResult = sessionOutput.config().getPlanFormat() == SessionConfig.PlanFormat.STRING;
+ sessionOutput.config().set(SessionConfig.FORMAT_QUOTE_RECORD, quoteResult);
+ ResultUtil.printResults(appCtx, advisor.getResultJson().toString(), sessionOutput,
+ new IStatementExecutor.Stats(), null);
+ }
+
+ @Override
+ public String getName() {
+ return ResultsPrinter.FIELD_NAME;
+ }
+
+}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
index bdbcbfb39a..888bef14a3 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/app/translator/QueryTranslator.java
@@ -5503,7 +5503,7 @@ public class QueryTranslator extends AbstractLangTranslator implements IStatemen
MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
stats.setCompileTime(System.nanoTime() - compileStart);
bActiveTxn = false;
- return query.isExplain() || isCompileOnly() ? null : jobSpec;
+ return query.isExplain() || query.isAdvise() || isCompileOnly() ? null : jobSpec;
} catch (Exception e) {
LOGGER.log(Level.INFO, e.getMessage(), e);
if (bActiveTxn) {
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
index 93233497dd..267a8c8a6a 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/utils/FeedOperations.java
@@ -213,7 +213,7 @@ public class FeedOperations {
whereClause != null ? Collections.singletonList(whereClause) : null, null, null);
SelectSetOperation selectSetOperation = new SelectSetOperation(new SetOperationInput(selectBlock, null), null);
SelectExpression body = new SelectExpression(null, selectSetOperation, null, null, true);
- Query query = new Query(false, true, body, 0);
+ Query query = new Query(false, false, true, body, 0);
return query;
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/CBOJoinQueries.xml b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/CBOJoinQueries.xml
index 26eb5ca4e0..67691a3eaa 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/CBOJoinQueries.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/CBOJoinQueries.xml
@@ -21,5 +21,29 @@
<output-dir compare="Text">ch2</output-dir>
</compilation-unit>
</test-case>
- ! Unless required by applicable la
+ <test-case FilePath="cbo-join/index-advisor">
+ <compilation-unit name="simple-advise">
+ <output-dir compare="Text">simple-advise</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="cbo-join/index-advisor">
+ <compilation-unit name="simple-advise1">
+ <output-dir compare="Text">simple-advise1</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="cbo-join/index-advisor">
+ <compilation-unit name="simple-advise2">
+ <output-dir compare="Text">simple-advise2</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="cbo-join/index-advisor">
+ <compilation-unit name="nested-fields">
+ <output-dir compare="Text">nested-fields</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="cbo-join/index-advisor">
+ <compilation-unit name="join-advise">
+ <output-dir compare="Text">join-advise</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.1.ddl.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.1.ddl.sqlpp
index 07a80349a7..7068064fff 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.1.ddl.sqlpp
@@ -16,15 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+drop dataverse test if exists;
+create dataverse test;
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+CREATE DATASET A PRIMARY KEY ( a_0 : integer);
+CREATE DATASET B PRIMARY KEY ( b_0 : integer);
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.2.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.2.update.sqlpp
index 07a80349a7..c0addba0f9 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.2.update.sqlpp
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+INSERT INTO A(
+ SELECT VALUE {"a_0": i, "a_1": 1 , "a_2" : i%5 }
+ FROM range(1, 1000) i
+);
+
+INSERT INTO B(
+ SELECT VALUE {"b_0": i, "b_1" : i ,"b_2": i}
+ FROM range(1, 1000) i
+);
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.3.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.3.update.sqlpp
index 07a80349a7..686e092211 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.3.update.sqlpp
@@ -16,15 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+use test;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ANALYZE DATASET A with {"sample": "high", "sample-seed": 2};
+ANALYZE DATASET B with {"sample": "high", "sample-seed": 2};
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.4.query.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.4.query.sqlpp
index 07a80349a7..b74f810bc1 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/join-advise/join-advise.4.query.sqlpp
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,15 +17,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ADVISE SELECT A.a_0, A.a_1, A.a_2, B.b_0, B.b_1, B.b_2
+ FROM A JOIN B ON (
+ A.a_1 = B.b_1)
+ WHERE A.a_2 = 1;
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.1.ddl.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.1.ddl.sqlpp
index 07a80349a7..cce6346f97 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.1.ddl.sqlpp
@@ -16,15 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+drop dataverse test if exists;
+create dataverse test;
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+CREATE DATASET A PRIMARY KEY ( a_0 : integer);
+CREATE DATASET B PRIMARY KEY ( b_0 : integer);
+
+CREATE INDEX idx_2 ON A(a_1.n_1.`n_2 field name`.`n_3`: time) CAST (DEFAULT NULL time 'hh:mm:ss.nnna');
+CREATE INDEX i3 ON B(UNNEST b.c UNNEST d.e UNNEST t SELECT x.y : string, q.w: int, u: int) EXCLUDE UNKNOWN KEY;
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.2.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.2.update.sqlpp
index 07a80349a7..67f4df518f 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.2.update.sqlpp
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+INSERT INTO A(
+ SELECT VALUE {"a_0" : i , "a_1": { "n_1 field" :{ "n_2 name" : i%20 }}, "a_2" : { "n_1 field" :{ "n_2 name" : i }} }
+ FROM range(1, 1000) i
+);
+
+INSERT INTO B(
+ SELECT VALUE {"b_0": i, "b_1" : { "n_1 field" :{ "n_2 name" : i }} ,"b_2": { "n_1 field" :{ "n_2 name" : i }}}
+ FROM range(1, 500) i
+);
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.3.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.3.update.sqlpp
index 07a80349a7..dadb7f1f76 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.3.update.sqlpp
@@ -16,15 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+use test;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ANALYZE DATASET A with {"sample": "high", "sample-seed": 2};
+ANALYZE DATASET B with {"sample": "high", "sample-seed": 2};
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.4.query.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.4.query.sqlpp
index 07a80349a7..3732f411c7 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/nested-fields/nested-fields.4.query.sqlpp
@@ -16,15 +16,14 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+use test;
+
+
+ADVISE
+SELECT *
+FROM A
+WHERE A.a_2.`n_1 field`.`n_2 name` = 1 AND repeat(A.a_1.`n_1 field`.`n_2 name`, 2) = "aa";
+
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.1.ddl.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.1.ddl.sqlpp
index 07a80349a7..18cf0e6e64 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.1.ddl.sqlpp
@@ -16,15 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+drop dataverse test if exists;
+create dataverse test;
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+CREATE DATASET A PRIMARY KEY ( a_0 : integer);
+CREATE DATASET B PRIMARY KEY ( b_0 : integer);
+
+CREATE INDEX idx_a_1 ON A(a_1);
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.2.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.2.update.sqlpp
index 07a80349a7..36c0078035 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.2.update.sqlpp
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+INSERT INTO A(
+ SELECT VALUE {"a_0": i, "a_1": i%20 , "a_2" : i }
+ FROM range(1, 1000) i
+);
+
+INSERT INTO B(
+ SELECT VALUE {"b_0": i, "b_1" : i ,"b_2": i}
+ FROM range(1, 500) i
+);
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.3.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.3.update.sqlpp
index 07a80349a7..dadb7f1f76 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.3.update.sqlpp
@@ -16,15 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+use test;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ANALYZE DATASET A with {"sample": "high", "sample-seed": 2};
+ANALYZE DATASET B with {"sample": "high", "sample-seed": 2};
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.4.query.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.4.query.sqlpp
index 07a80349a7..37c4659b4e 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise/simple-advise.4.query.sqlpp
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,15 +17,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ADVISE SELECT A.a_0, A.a_1, A.a_2, B.b_0, B.b_1, B.b_2
+FROM A JOIN B ON (
+ A.a_2 = B.b_2)
+WHERE A.a_1 = 1;
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.1.ddl.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.1.ddl.sqlpp
index 07a80349a7..e3f9e43baf 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.1.ddl.sqlpp
@@ -16,15 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+drop dataverse test if exists;
+create dataverse test;
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+CREATE DATASET A PRIMARY KEY ( id : integer);
+CREATE DATASET B PRIMARY KEY ( id : integer);
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.2.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.2.update.sqlpp
index 07a80349a7..e3fbe85c48 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.2.update.sqlpp
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+INSERT INTO A(
+ SELECT VALUE {"id": intVal, "a": intVal%2, "b": intVal%25 , "d": intVal%25}
+ FROM range(1, 1000) intVal
+);
+
+INSERT INTO B(
+ SELECT VALUE {"id": intVal, "a": intVal%5, "c": intVal%25}
+ FROM range(1, 1000) intVal
+);
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.3.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.3.update.sqlpp
index 07a80349a7..4a1c864aaf 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.3.update.sqlpp
@@ -16,15 +16,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+use test;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
-
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ANALYZE DATASET A with {"sample": "high", "sample-seed": 2};
+ANALYZE DATASET B with {"sample": "high", "sample-seed": 2};
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.4.query.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.4.query.sqlpp
index 07a80349a7..2357984936 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.4.query.sqlpp
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,15 +17,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ADVISE select * from A
+ where A.b=1 ;
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.5.query.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.5.query.sqlpp
index 07a80349a7..a9517626d7 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise1/simple-advise1.5.query.sqlpp
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,15 +17,8 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ADVISE select * from A join B on A.a=B.a
+ where A.b=1 AND B.c=2;
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.1.ddl.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.1.ddl.sqlpp
index 07a80349a7..432f897d6b 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.1.ddl.sqlpp
@@ -16,15 +16,11 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+drop dataverse test if exists;
+create dataverse test;
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+CREATE DATASET A PRIMARY KEY ( pa : integer);
+CREATE DATASET B PRIMARY KEY ( pb : integer);
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.2.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.2.update.sqlpp
index 07a80349a7..0fd47f4a50 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.2.update.sqlpp
@@ -16,15 +16,16 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+INSERT INTO A(
+ SELECT VALUE { "pa" : i , "a0": i%2, "a1": i%40 , "a2" : i%30 , "a3" : i%5, "a4" : i }
+ FROM range(1, 500) i
+);
+
+INSERT INTO B(
+ SELECT VALUE { "pb" : i , "b3" : 5, "b4" : i }
+ FROM range(1, 500) i
+);
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.3.update.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.3.update.sqlpp
index 07a80349a7..686e092211 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.3.update.sqlpp
@@ -16,15 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+use test;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ANALYZE DATASET A with {"sample": "high", "sample-seed": 2};
+ANALYZE DATASET B with {"sample": "high", "sample-seed": 2};
\ No newline at end of file
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.4.query.sqlpp
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.4.query.sqlpp
index 07a80349a7..6a9bb9964f 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries_sqlpp/cbo-join/index-advisor/simple-advise2/simple-advise2.4.query.sqlpp
@@ -1,3 +1,4 @@
+
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
@@ -16,15 +17,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
-
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+use test;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
-}
+ADVISE
+SELECT *
+FROM A
+JOIN B ON A.a3 = B.b3 AND A.a4 = B.b4
+WHERE A.a0 = 0 AND A.a1 = 0 AND A.a2 = 0
+and sleep(A.a5,10) = 0
+;
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/join-advise/join-advise.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/join-advise/join-advise.4.adm
new file mode 100644
index 0000000000..42da673db7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/join-advise/join-advise.4.adm
@@ -0,0 +1 @@
+[{"#operator":"Advise","advice":{"#operator":"IndexAdvice","adviseinfo":{"current_indexes":[],"recommended_indexes":{"indexes":[{"index_statement":"CREATE INDEX idx_b_1 ON `Default`.`test`.`B`(`b_1`);"}]}}}}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/nested-fields/nested-fields.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/nested-fields/nested-fields.4.adm
new file mode 100644
index 0000000000..db990cb9bb
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/nested-fields/nested-fields.4.adm
@@ -0,0 +1 @@
+[{"#operator":"Advise","advice":{"#operator":"IndexAdvice","adviseinfo":{"current_indexes":[],"recommended_indexes":{"indexes":[{"index_statement":"CREATE INDEX idx_a_2_n_1field_n_2name ON `Default`.`test`.`A`(`a_2`.`n_1 field`.`n_2 name`);"}]}}}}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise/simple-advise.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise/simple-advise.4.adm
new file mode 100644
index 0000000000..55150dedd9
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise/simple-advise.4.adm
@@ -0,0 +1 @@
+[{"#operator":"Advise","advice":{"#operator":"IndexAdvice","adviseinfo":{"current_indexes":[{"index_statement":"CREATE INDEX idx_a_1 ON `Default`.`test`.`A`(`a_1`);"}],"recommended_indexes":{"indexes":[{"index_statement":"CREATE INDEX idx_b_2 ON `Default`.`test`.`B`(`b_2`);"}]}}}}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise1/simple-advise1.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise1/simple-advise1.4.adm
new file mode 100644
index 0000000000..e2b4c29dde
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise1/simple-advise1.4.adm
@@ -0,0 +1 @@
+[{"#operator":"Advise","advice":{"#operator":"IndexAdvice","adviseinfo":{"current_indexes":[],"recommended_indexes":{"indexes":[{"index_statement":"CREATE INDEX idx_b ON `Default`.`test`.`A`(`b`);"}]}}}}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise1/simple-advise1.5.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise1/simple-advise1.5.adm
new file mode 100644
index 0000000000..e2b4c29dde
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise1/simple-advise1.5.adm
@@ -0,0 +1 @@
+[{"#operator":"Advise","advice":{"#operator":"IndexAdvice","adviseinfo":{"current_indexes":[],"recommended_indexes":{"indexes":[{"index_statement":"CREATE INDEX idx_b ON `Default`.`test`.`A`(`b`);"}]}}}}]
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise2/simple-advise2.4.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise2/simple-advise2.4.adm
new file mode 100644
index 0000000000..f519cd1246
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/cbo-join/index-advisor/simple-advise2/simple-advise2.4.adm
@@ -0,0 +1 @@
+[{"#operator":"Advise","advice":{"#operator":"IndexAdvice","adviseinfo":{"current_indexes":[],"recommended_indexes":{"indexes":[{"index_statement":"CREATE INDEX idx_a0_a1_a2 ON `Default`.`test`.`A`(`a0`,`a1`,`a2`);"}]}}}}]
\ No newline at end of file
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java
index 7332c7d226..2e3974bab4 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/statement/Query.java
@@ -31,20 +31,23 @@ import org.apache.asterix.lang.common.visitor.base.ILangVisitor;
public class Query extends AbstractStatement implements IReturningStatement {
private boolean explain;
+ private boolean advise;
private boolean topLevel = true;
private Expression body;
private int varCounter;
public Query() {
- this(false);
+ this(false, false);
}
- public Query(boolean explain) {
+ public Query(boolean explain, boolean advise) {
this.explain = explain;
+ this.advise = advise;
}
- public Query(boolean explain, boolean topLevel, Expression body, int varCounter) {
+ public Query(boolean explain, boolean advise, boolean topLevel, Expression body, int varCounter) {
this.explain = explain;
+ this.advise = advise;
this.topLevel = topLevel;
this.body = body;
this.varCounter = varCounter;
@@ -88,10 +91,18 @@ public class Query extends AbstractStatement implements IReturningStatement {
this.explain = explain;
}
+ public void setAdvise(boolean advise) {
+ this.advise = advise;
+ }
+
public boolean isExplain() {
return explain;
}
+ public boolean isAdvise() {
+ return advise;
+ }
+
@Override
public Kind getKind() {
return Statement.Kind.QUERY;
@@ -104,7 +115,7 @@ public class Query extends AbstractStatement implements IReturningStatement {
@Override
public int hashCode() {
- return Objects.hash(body, topLevel, explain, varCounter);
+ return Objects.hash(body, topLevel, explain, advise, varCounter);
}
@Override
@@ -117,7 +128,7 @@ public class Query extends AbstractStatement implements IReturningStatement {
}
Query target = (Query) object;
return explain == target.explain && Objects.equals(body, target.body) && topLevel == target.topLevel
- && varCounter == target.varCounter;
+ && varCounter == target.varCounter && advise == target.advise;
}
@Override
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
index a7de54124c..afa2effa65 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/util/ExpressionUtils.java
@@ -369,7 +369,7 @@ public class ExpressionUtils {
}
public static Query createWrappedQuery(Expression expr, SourceLocation sourceLoc) {
- Query wrappedQuery = new Query(false);
+ Query wrappedQuery = new Query(false, false);
wrappedQuery.setSourceLocation(sourceLoc);
wrappedQuery.setBody(expr);
wrappedQuery.setTopLevel(false);
diff --git a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
index 4f09722921..c515cdd52d 100644
--- a/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
+++ b/asterixdb/asterix-lang-common/src/main/java/org/apache/asterix/lang/common/visitor/CloneAndSubstituteVariablesVisitor.java
@@ -264,7 +264,7 @@ public class CloneAndSubstituteVariablesVisitor extends
@Override
public Pair<ILangExpression, VariableSubstitutionEnvironment> visit(Query q, VariableSubstitutionEnvironment env)
throws CompilationException {
- Query newQ = new Query(q.isExplain());
+ Query newQ = new Query(q.isExplain(), q.isAdvise());
Pair<ILangExpression, VariableSubstitutionEnvironment> p1 = q.getBody().accept(this, env);
newQ.setBody((Expression) p1.first);
newQ.setSourceLocation(q.getSourceLocation());
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java
index d15eb2ddf0..ef38f58cab 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/rewrites/visitor/SqlppCopyToRewriteVisitor.java
@@ -82,7 +82,7 @@ public class SqlppCopyToRewriteVisitor extends AbstractSqlppAstVisitor<Void, Met
selectSetOperation.setSourceLocation(var.getSourceLocation());
SelectExpression selectExpression = new SelectExpression(null, selectSetOperation, null, null, false);
selectExpression.setSourceLocation(var.getSourceLocation());
- Query query = new Query(false, false, selectExpression, 0);
+ Query query = new Query(false, false, false, selectExpression, 0);
query.setBody(selectExpression);
query.setSourceLocation(stmtCopy.getSourceLocation());
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
index 62acfebe0a..f48cd99291 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/util/SqlppRewriteUtil.java
@@ -89,7 +89,7 @@ public class SqlppRewriteUtil {
}
// Creates a wrapper query for the expression so that if the expression itself
// is the key, it can also be replaced.
- Query wrapper = new Query(false);
+ Query wrapper = new Query(false, false);
wrapper.setSourceLocation(expression.getSourceLocation());
wrapper.setBody(expression);
// Creates a substitution visitor.
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
index 9941dded4b..018ba69a94 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/DeepCopyVisitor.java
@@ -258,8 +258,8 @@ public class DeepCopyVisitor extends AbstractSqlppQueryExpressionVisitor<ILangEx
@Override
public Query visit(Query q, Void arg) throws CompilationException {
- Query copy =
- new Query(q.isExplain(), q.isTopLevel(), (Expression) q.getBody().accept(this, arg), q.getVarCounter());
+ Query copy = new Query(q.isExplain(), q.isAdvise(), q.isTopLevel(), (Expression) q.getBody().accept(this, arg),
+ q.getVarCounter());
copy.setSourceLocation(q.getSourceLocation());
return copy;
}
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppDeleteRewriteVisitor.java b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppDeleteRewriteVisitor.java
index 62e4d23719..72e9b450b2 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppDeleteRewriteVisitor.java
+++ b/asterixdb/asterix-lang-sqlpp/src/main/java/org/apache/asterix/lang/sqlpp/visitor/SqlppDeleteRewriteVisitor.java
@@ -96,7 +96,7 @@ public class SqlppDeleteRewriteVisitor extends AbstractSqlppAstVisitor<Void, Met
selectSetOperation.setSourceLocation(var.getSourceLocation());
SelectExpression selectExpression = new SelectExpression(null, selectSetOperation, null, null, false);
selectExpression.setSourceLocation(var.getSourceLocation());
- Query query = new Query(false, false, selectExpression, 0);
+ Query query = new Query(false, false, false, selectExpression, 0);
query.setBody(selectExpression);
query.setSourceLocation(deleteStmt.getSourceLocation());
diff --git a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
index 34f5ba0af0..cbd1f490ae 100644
--- a/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
+++ b/asterixdb/asterix-lang-sqlpp/src/main/javacc/SQLPP.jj
@@ -276,6 +276,7 @@ class SQLPPParser extends ScopeChecker implements IParser {
private static final String RETURNS = "RETURNS";
private static final String CONFIG = "CONFIG";
private static final String STATISTICS = "STATISTICS";
+ private static final String ADVISE = "ADVISE";
private static final String INT_TYPE_NAME = "int";
@@ -973,7 +974,7 @@ List<Statement> Statement() throws ParseException:
}
{
(
- (stmt = ExplainStatement()
+ (stmt = ExplainOrAdviseStatement()
{
decls.add(stmt);
}
@@ -986,16 +987,21 @@ List<Statement> Statement() throws ParseException:
}
}
-Statement ExplainStatement() throws ParseException:
+Statement ExplainOrAdviseStatement() throws ParseException:
{
Statement stmt = null;
Token explainToken = null;
+ boolean adviseToken = false;
}
{
- ( <EXPLAIN> { explainToken = token; } )?
+( <EXPLAIN> { explainToken = token; } | LOOKAHEAD({ laIdentifier(ADVISE) }) <IDENTIFIER> { adviseToken = true; } )?
stmt = SingleStatement()
{
- if (explainToken != null) {
+ if (explainToken != null && adviseToken ) {
+ throw new SqlppParseException(getSourceLocation(explainToken),
+ "EXPLAIN and ADVISE cannot be used together");
+ }
+ if (explainToken != null ) {
if (stmt.getKind() == Statement.Kind.QUERY) {
((Query)stmt).setExplain(true);
} else {
@@ -1003,6 +1009,14 @@ Statement ExplainStatement() throws ParseException:
"EXPLAIN is not supported for this kind of statement");
}
}
+ if (adviseToken ) {
+ if (stmt.getKind() == Statement.Kind.QUERY) {
+ ((Query)stmt).setAdvise(true);
+ } else {
+ throw new SqlppParseException(getSourceLocation(token),
+ "ADVISE is not supported for statement kind: "+ stmt.getKind());
+ }
+ }
return stmt;
}
}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IIndexProvider.java
similarity index 57%
copy from hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
copy to asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IIndexProvider.java
index 07a80349a7..5e4593244b 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/IIndexProvider.java
@@ -16,15 +16,18 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.hyracks.algebricks.compiler.api;
+package org.apache.asterix.metadata.declared;
-import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
-import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
-import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
-import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
+import java.util.List;
-public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+import org.apache.asterix.common.metadata.DataverseName;
+import org.apache.asterix.metadata.entities.Index;
+import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
- ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
+public interface IIndexProvider {
+ Index getIndex(String database, DataverseName dataverseName, String datasetName, String indexName)
+ throws AlgebricksException;
+
+ List<Index> getDatasetIndexes(String database, DataverseName dataverseName, String datasetName)
+ throws AlgebricksException;
}
diff --git a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
index b0291375b2..464f6d8319 100644
--- a/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
+++ b/asterixdb/asterix-metadata/src/main/java/org/apache/asterix/metadata/declared/MetadataProvider.java
@@ -177,7 +177,7 @@ import org.apache.hyracks.storage.am.rtree.dataflow.RTreeSearchOperatorDescripto
import org.apache.hyracks.storage.common.IStorageManager;
import org.apache.hyracks.storage.common.projection.ITupleProjectorFactory;
-public class MetadataProvider implements IMetadataProvider<DataSourceId, String> {
+public class MetadataProvider implements IMetadataProvider<DataSourceId, String>, IIndexProvider {
private final ICcApplicationContext appCtx;
private final IStorageComponentProvider storageComponentProvider;
@@ -463,11 +463,13 @@ public class MetadataProvider implements IMetadataProvider<DataSourceId, String>
return index != null ? new DataSourceIndex(index, database, dataverseName, datasetName, this) : null;
}
+ @Override
public Index getIndex(String database, DataverseName dataverseName, String datasetName, String indexName)
throws AlgebricksException {
return MetadataManager.INSTANCE.getIndex(mdTxnCtx, database, dataverseName, datasetName, indexName);
}
+ @Override
public List<Index> getDatasetIndexes(String database, DataverseName dataverseName, String datasetName)
throws AlgebricksException {
return MetadataManagerUtil.getDatasetIndexes(mdTxnCtx, database, dataverseName, datasetName);
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
index 3a2fe3bbbd..b2b223e95e 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/AbstractCompilerFactoryBuilder.java
@@ -57,6 +57,7 @@ public abstract class AbstractCompilerFactoryBuilder {
protected Supplier<List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>>> logicalRewrites;
protected Function<IRuleSetKind, List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>>> logicalRewritesByKind;
protected Supplier<List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>>> physicalRewrites;
+ protected Function<IRuleSetKind, List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>>> physicalRewritesByKind;
protected ITypeTraitProvider typeTraitProvider;
protected ISerializerDeserializerProvider serializerDeserializerProvider;
protected IBinaryHashFunctionFactoryProvider hashFunctionFactoryProvider;
@@ -101,6 +102,11 @@ public abstract class AbstractCompilerFactoryBuilder {
this.physicalRewrites = physicalRewrites;
}
+ public void setPhysicalRewritesByKind(
+ Function<IRuleSetKind, List<Pair<AbstractRuleController, List<IAlgebraicRewriteRule>>>> physicalRewritesByKind) {
+ this.physicalRewritesByKind = physicalRewritesByKind;
+ }
+
public void setTypeTraitProvider(ITypeTraitProvider typeTraitProvider) {
this.typeTraitProvider = typeTraitProvider;
}
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
index a44e1be35e..a994fa3e31 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/HeuristicCompilerFactoryBuilder.java
@@ -26,6 +26,7 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.common.utils.Pair;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
@@ -66,12 +67,13 @@ public class HeuristicCompilerFactoryBuilder extends AbstractCompilerFactoryBuil
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
IConflictingTypeResolver conflictingTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector) {
+ AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector,
+ IndexAdvisor indexAdvisor) {
IPlanPrettyPrinter prettyPrinter = PlanPrettyPrinter.createStringPlanPrettyPrinter();
return new AlgebricksOptimizationContext(this, varCounter, expressionEvalSizeComputer,
mergeAggregationExpressionFactory, expressionTypeComputer, missableTypeComputer,
conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, prettyPrinter,
- warningCollector);
+ warningCollector, indexAdvisor);
}
@Override
@@ -97,15 +99,16 @@ public class HeuristicCompilerFactoryBuilder extends AbstractCompilerFactoryBuil
private class CompilerFactoryImpl implements ICompilerFactory {
@Override
- public ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter) {
- IOptimizationContext optContext =
- optCtxFactory.createOptimizationContext(varCounter, expressionEvalSizeComputer,
- mergeAggregationExpressionFactory, expressionTypeComputer, missableTypeComputer,
- conflictingTypeResolver, physicalOptimizationConfig, clusterLocations, warningCollector);
+ public ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter,
+ IRuleSetKind ruleSetKind, IndexAdvisor indexAdvisor) {
+ IOptimizationContext optContext = optCtxFactory.createOptimizationContext(varCounter,
+ expressionEvalSizeComputer, mergeAggregationExpressionFactory, expressionTypeComputer,
+ missableTypeComputer, conflictingTypeResolver, physicalOptimizationConfig, clusterLocations,
+ warningCollector, indexAdvisor);
optContext.setMetadataDeclarations(metadata);
optContext.setCompilerFactory(this);
- return new CompilerImpl(this, plan, optContext, logicalRewrites.get(), physicalRewrites.get(),
- writerFactory);
+ return new CompilerImpl(this, plan, optContext, logicalRewritesByKind.apply(ruleSetKind),
+ physicalRewritesByKind.apply(ruleSetKind), writerFactory);
}
@Override
diff --git a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
index 07a80349a7..dbf45cc609 100644
--- a/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
+++ b/hyracks-fullstack/algebricks/algebricks-compiler/src/main/java/org/apache/hyracks/algebricks/compiler/api/ICompilerFactory.java
@@ -20,11 +20,13 @@ package org.apache.hyracks.algebricks.compiler.api;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalPlan;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
import org.apache.hyracks.algebricks.core.algebra.metadata.IMetadataProvider;
import org.apache.hyracks.algebricks.core.rewriter.base.IRuleSetKind;
public interface ICompilerFactory {
- ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter);
+ ICompiler createCompiler(ILogicalPlan plan, IMetadataProvider<?, ?> metadata, int varCounter,
+ IRuleSetKind ruleSetKind, IndexAdvisor indexAdvisor);
ICompiler createCompiler(ILogicalPlan plan, IOptimizationContext newOptContext, IRuleSetKind ruleSetKind);
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java
index 10b04516f1..78cbf7f0c5 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IOptimizationContext.java
@@ -104,4 +104,7 @@ public interface IOptimizationContext extends ITypingContext, IVariableContext {
default boolean skipJobCapacityAssignment() {
return false;
}
+
+ IndexAdvisor getIndexAdvisor();
+
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IndexAdvisor.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IndexAdvisor.java
new file mode 100644
index 0000000000..d381afab43
--- /dev/null
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/algebra/base/IndexAdvisor.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.hyracks.algebricks.core.algebra.base;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+public class IndexAdvisor {
+ private final boolean isAdvise;
+ private Object fakeIndexProvider;
+ private final List<Advise> recommendedAdvise;
+ private final List<Advise> presentAdvise;
+ private static final JsonNode template;
+
+ static {
+ try {
+ template = new ObjectMapper().readTree("""
+ [
+ {
+ "#operator": "Advise",
+ "advice": {
+ "#operator": "IndexAdvice",
+ "adviseinfo": {
+ "current_indexes": [ ],
+ "recommended_indexes": {
+ "indexes": [ ]
+ }
+ }
+ }
+ }
+ ]
+ """);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public IndexAdvisor(boolean isAdvise) {
+ this.isAdvise = isAdvise;
+ recommendedAdvise = new ArrayList<>();
+ presentAdvise = new ArrayList<>();
+ }
+
+ public boolean getAdvise() {
+ return isAdvise;
+ }
+
+ public void addRecommendedAdvise(String indexName, List<List<String>> keyFieldNames, String databaseName,
+ String dataverseName, String datasetName) {
+ recommendedAdvise.add(new Advise(indexName, keyFieldNames, databaseName, dataverseName, datasetName));
+ }
+
+ public void addPresentAdvise(String indexName, List<List<String>> keyFieldNames, String databaseName,
+ String dataverseName, String datasetName) {
+ presentAdvise.add(new Advise(indexName, keyFieldNames, databaseName, dataverseName, datasetName));
+ }
+
+ public void setFakeIndexProvider(Object fakeIndexProvider) {
+ this.fakeIndexProvider = fakeIndexProvider;
+ }
+
+ public Object getFakeIndexProvider() {
+ return fakeIndexProvider;
+ }
+
+ public JsonNode getResultJson() {
+
+ JsonNode resultJson = template.deepCopy();
+ ArrayNode currentIndexNode =
+ (ArrayNode) resultJson.path(0).path("advice").path("adviseinfo").path("current_indexes");
+ for (Advise advise : presentAdvise) {
+ ObjectNode indexNode = JsonNodeFactory.instance.objectNode();
+ indexNode.put("index_statement", advise.getCreateIndexClause());
+ currentIndexNode.add(indexNode);
+ }
+
+ ArrayNode recommendedIndexNode = (ArrayNode) resultJson.path(0).path("advice").path("adviseinfo")
+ .path("recommended_indexes").path("indexes");
+
+ for (Advise advise : recommendedAdvise) {
+ ObjectNode indexNode = JsonNodeFactory.instance.objectNode();
+ indexNode.put("index_statement", advise.getCreateIndexClause());
+ recommendedIndexNode.add(indexNode);
+ }
+ return resultJson; // Placeholder for actual implementation
+ }
+
+ static public class Advise {
+ private final String indexName;
+ private final List<List<String>> keyFieldNames;
+ private final String databaseName;
+ private final String dataverseName;
+ private final String datasetName;
+
+ public Advise(String indexName, List<List<String>> keyFieldNames, String databaseName, String dataverseName,
+ String datasetName) {
+ this.indexName = indexName;
+ this.keyFieldNames = keyFieldNames;
+ this.databaseName = databaseName;
+ this.dataverseName = dataverseName;
+ this.datasetName = datasetName;
+ }
+
+ public String getIndexName() {
+ return indexName;
+ }
+
+ public String getCreateIndexClause() {
+
+ return "CREATE INDEX " + indexName + " ON `" + databaseName + "`.`" + dataverseName + "`.`" + datasetName
+ + "`" + getKeyFieldNamesClause() + ";";
+ }
+
+ public String getKeyFieldNamesClause() {
+ return keyFieldNames.stream()
+ .map(fields -> fields.stream().map(s -> "`" + s + "`").collect(Collectors.joining(".")))
+ .collect(Collectors.joining(",", "(", ")"));
+
+ }
+
+ }
+
+}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
index bee842ce70..ae9767867b 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/AlgebricksOptimizationContext.java
@@ -29,6 +29,7 @@ import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
import org.apache.hyracks.algebricks.core.algebra.base.EquivalenceClass;
import org.apache.hyracks.algebricks.core.algebra.base.ILogicalOperator;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
import org.apache.hyracks.algebricks.core.algebra.base.LogicalVariable;
import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
@@ -81,6 +82,7 @@ public class AlgebricksOptimizationContext implements IOptimizationContext {
private int varCounter;
private IMetadataProvider metadataProvider;
private Object compilerFactory;
+ private IndexAdvisor indexAdvisor;
public AlgebricksOptimizationContext(IOptimizationContextFactory optContextFactory, int varCounter,
IExpressionEvalSizeComputer expressionEvalSizeComputer,
@@ -88,7 +90,7 @@ public class AlgebricksOptimizationContext implements IOptimizationContext {
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer nullableTypeComputer,
IConflictingTypeResolver conflictingTypeResovler, PhysicalOptimizationConfig physicalOptimizationConfig,
AlgebricksPartitionConstraint clusterLocations, IPlanPrettyPrinter prettyPrinter,
- IWarningCollector warningCollector) {
+ IWarningCollector warningCollector, IndexAdvisor indexAdvisor) {
this.optContextFactory = optContextFactory;
this.varCounter = varCounter;
this.expressionEvalSizeComputer = expressionEvalSizeComputer;
@@ -103,6 +105,7 @@ public class AlgebricksOptimizationContext implements IOptimizationContext {
boolean isSanityCheckEnabled = physicalOptimizationConfig.isSanityCheckEnabled();
this.planStructureVerifier = isSanityCheckEnabled ? new PlanStructureVerifier(prettyPrinter, this) : null;
this.planStabilityVerifier = isSanityCheckEnabled ? new PlanStabilityVerifier(prettyPrinter) : null;
+ this.indexAdvisor = indexAdvisor;
}
public AlgebricksOptimizationContext(AlgebricksOptimizationContext from) {
@@ -122,6 +125,7 @@ public class AlgebricksOptimizationContext implements IOptimizationContext {
planStabilityVerifier = isSanityCheckEnabled ? new PlanStabilityVerifier(from.prettyPrinter) : null;
metadataProvider = from.metadataProvider;
compilerFactory = from.compilerFactory;
+ indexAdvisor = from.indexAdvisor;
varEvalSizeEnv.varSizeMap.putAll(from.varEvalSizeEnv.varSizeMap);
typeEnvMap.putAll(from.typeEnvMap);
@@ -403,4 +407,10 @@ public class AlgebricksOptimizationContext implements IOptimizationContext {
return varSizeMap.get(var);
}
}
+
+ @Override
+ public IndexAdvisor getIndexAdvisor() {
+ return indexAdvisor;
+ }
+
}
diff --git a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java
index c81025d82e..770aad59f8 100644
--- a/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java
+++ b/hyracks-fullstack/algebricks/algebricks-core/src/main/java/org/apache/hyracks/algebricks/core/rewriter/base/IOptimizationContextFactory.java
@@ -20,6 +20,7 @@ package org.apache.hyracks.algebricks.core.rewriter.base;
import org.apache.hyracks.algebricks.common.constraints.AlgebricksPartitionConstraint;
import org.apache.hyracks.algebricks.core.algebra.base.IOptimizationContext;
+import org.apache.hyracks.algebricks.core.algebra.base.IndexAdvisor;
import org.apache.hyracks.algebricks.core.algebra.expressions.IConflictingTypeResolver;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionEvalSizeComputer;
import org.apache.hyracks.algebricks.core.algebra.expressions.IExpressionTypeComputer;
@@ -33,7 +34,8 @@ public interface IOptimizationContextFactory {
IMergeAggregationExpressionFactory mergeAggregationExpressionFactory,
IExpressionTypeComputer expressionTypeComputer, IMissableTypeComputer missableTypeComputer,
IConflictingTypeResolver conflictintTypeResolver, PhysicalOptimizationConfig physicalOptimizationConfig,
- AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector);
+ AlgebricksPartitionConstraint clusterLocations, IWarningCollector warningCollector,
+ IndexAdvisor indexAdvisor);
IOptimizationContext cloneOptimizationContext(IOptimizationContext oc);
}