You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@asterixdb.apache.org by AsterixDB Code Review <do...@asterix-gerrit.ics.uci.edu> on 2026/08/24 11:58:44 UTC
[L] Change in asterixdb[master]: [NO ISSUE][COMP] Cap the number of FROM terms the CBO enumerates
From Rithwik Koul <ri...@couchbase.com>:
Rithwik Koul has uploaded this change for review. ( https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21608?usp=email )
Change subject: [NO ISSUE][COMP] Cap the number of FROM terms the CBO enumerates
......................................................................
[NO ISSUE][COMP] Cap the number of FROM terms the CBO enumerates
- user model changes: no
- storage format changes: no
- interface changes: no
The join node array that join and plan enumeration allocates holds
2^numberOfFromTerms entries, so a statement with many FROM terms asks
for an unreasonable amount of memory: 26 FROM terms need about 22GB.
Skip the cost based optimizer when the number of FROM terms exceeds
"cbomaxfromterms" (16 by default), and allocate the array only when the
enumeration actually starts, so that it is not allocated at all in the
cases where the cost based optimizer does not apply.
Ex-ref: MB-73496
Change-Id: Idb792d775b24fb5759cade2c764114939c502b06
---
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/EnumerateJoinsRule.java
M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/cbo/JoinEnum.java
A asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/max-from-terms.sqlpp
A asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/max-from-terms.plan
A asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/max-from-terms.plan
6 files changed, 312 insertions(+), 3 deletions(-)
git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb refs/changes/08/21608/1
diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
index aa4342e..b37b7a7 100644
--- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
+++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/compiler/provider/SqlppCompilationProvider.java
@@ -126,6 +126,6 @@
DisjunctivePredicateToJoinRule.REWRITE_OR_AS_JOIN_OPTION,
SetAsterixPhysicalOperatorsRule.REWRITE_ATTEMPT_BATCH_ASSIGN,
EquivalenceClassUtils.REWRITE_INTERNAL_QUERYUID_PK, SqlppQueryRewriter.SQL_COMPAT_OPTION,
- JoinEnum.CBO_FULL_ENUM_LEVEL_KEY, JoinEnum.CBO_CP_ENUM_KEY));
+ JoinEnum.CBO_FULL_ENUM_LEVEL_KEY, JoinEnum.CBO_CP_ENUM_KEY, JoinEnum.CBO_MAX_FROM_TERMS_KEY));
}
}
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 44a7bd0..0c1ccac 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
@@ -284,6 +284,15 @@
printPlan(pp, (AbstractLogicalOperator) op, "Original Whole plan2");
numberOfFromTerms = leafInputs.size();
+ int maxFromTerms = JoinEnum.getCBOMaxFromTerms(context);
+ if (numberOfFromTerms > maxFromTerms) {
+ // the memory needed to enumerate the join order grows as 2^numberOfFromTerms; leave the plan to the
+ // rule based optimizer instead.
+ LOGGER.info("Skipping CBO; number of FROM terms {} exceeds the maximum of {}", numberOfFromTerms,
+ maxFromTerms);
+ return cleanUp();
+ }
+
if (LOGGER.isTraceEnabled()) {
viewInPlan = new ALogicalPlanImpl(opRef).toString(); //useful when debugging
LOGGER.trace("viewInPlan");
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 dacc614..5050840 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
@@ -102,6 +102,11 @@
// Mode for cartesian product plan generation during join and plan enumeration
public static final String CBO_CP_ENUM_KEY = "cbocpenum";
private static final boolean CBO_CP_ENUM_DEFAULT = true;
+
+ // Maximum number of FROM terms for which join and plan enumeration is attempted; the join node array that the
+ // enumeration allocates holds 2^numberOfTerms entries
+ public static final String CBO_MAX_FROM_TERMS_KEY = "cbomaxfromterms";
+ private static final int CBO_MAX_FROM_TERMS_DEFAULT = 16;
protected List<JoinCondition> joinConditions; // "global" list of join conditions
protected Map<IExpressionAnnotation, Warning> joinHints;
protected Map<AbstractLeafInput, Integer> leafInputToJoinIndexMap;
@@ -186,7 +191,7 @@
this.op = op;
this.forceJoinOrderMode = getForceJoinOrderMode(context);
this.queryPlanShape = getQueryPlanShape(context);
- initCostHandleAndJoinNodes(context);
+ initCostHandle(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;
@@ -194,10 +199,14 @@
leafInputToJoinIndexMap = new HashMap<>();
}
- protected void initCostHandleAndJoinNodes(IOptimizationContext context) {
+ protected void initCostHandle(IOptimizationContext context) {
this.cost = new Cost();
this.costMethods = new CostMethods(context);
this.stats = new Stats(optCtx, this);
+ }
+
+ // The join node array holds 2^numberOfTerms entries, so it is allocated only when enumeration actually starts.
+ private void initJoinNodes() {
this.jnArraySize = (int) Math.pow(2.0, this.numberOfTerms);
this.jnArray = new JoinNode[this.jnArraySize];
// initialize all the join nodes
@@ -219,6 +228,18 @@
}
}
+ static int getCBOMaxFromTerms(IOptimizationContext context) throws AsterixException {
+ MetadataProvider mdp = (MetadataProvider) context.getMetadataProvider();
+
+ String valueInQuery = mdp.getProperty(CBO_MAX_FROM_TERMS_KEY);
+ try {
+ return valueInQuery == null ? CBO_MAX_FROM_TERMS_DEFAULT : OptionTypes.POSITIVE_INTEGER.parse(valueInQuery);
+ } catch (IllegalArgumentException e) {
+ throw AsterixException.create(ErrorCode.COMPILATION_BAD_QUERY_PARAMETER_VALUE, CBO_MAX_FROM_TERMS_KEY, 1,
+ "");
+ }
+ }
+
private boolean getCBOCPEnumMode(IOptimizationContext context) {
MetadataProvider mdp = (MetadataProvider) context.getMetadataProvider();
return mdp.getBooleanProperty(CBO_CP_ENUM_KEY, CBO_CP_ENUM_DEFAULT);
@@ -1345,6 +1366,7 @@
// main entry point in this file
protected AbstractPlanNode enumerateJoins() throws AlgebricksException {
+ initJoinNodes();
// create a localJoinOp for use in calling existing nested loops code.
InnerJoinOperator dummyInput = new InnerJoinOperator(null, null, null);
localJoinOp = new InnerJoinOperator(new MutableObject<>(ConstantExpression.TRUE),
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/max-from-terms.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/max-from-terms.sqlpp
new file mode 100644
index 0000000..755ee6e
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/joins/max-from-terms.sqlpp
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+/*
+ * Description : A query with more FROM terms than the join order enumeration is allowed to handle.
+ * Expected Res : The rule based optimizer plan, as the cost based optimizer is skipped.
+ */
+
+drop dataverse test if exists;
+create dataverse test;
+use test;
+
+create dataset ds(id uuid not unknown) open type primary key `id` autogenerated;
+
+set cbomaxfromterms "3";
+
+select count(*) from ds t1, ds t2, ds t3, ds t4
+where t1.x = t2.x and t2.x = t3.x and t3.x = t4.x;
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/max-from-terms.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/max-from-terms.plan
new file mode 100644
index 0000000..2d44122
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/joins/max-from-terms.plan
@@ -0,0 +1,116 @@
+distribute result [$$91]
+-- DISTRIBUTE_RESULT |UNPARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
+ assign [$$91] <- [{"$1": $$99}] project: [$$91]
+ -- ASSIGN |UNPARTITIONED|
+ aggregate [$$99] <- [agg-sql-sum($$101)]
+ -- AGGREGATE |UNPARTITIONED|
+ exchange
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ aggregate [$$101] <- [agg-sql-count(1)]
+ -- AGGREGATE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (eq($$92, $$98))
+ -- HYBRID_HASH_JOIN [$$92][$$98] |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ project ([$$92])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (eq($$93, $$92))
+ -- HYBRID_HASH_JOIN [$$93][$$92] |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ project ([$$93])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (eq($$100, $$93))
+ -- HYBRID_HASH_JOIN [$$100][$$93] |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$100] <- [$$93] project: [$$100]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate
+ -- REPLICATE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate
+ -- REPLICATE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$92] <- [$$93] project: [$$92]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate
+ -- REPLICATE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$98] <- [$$93] project: [$$98]
+ -- ASSIGN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate
+ -- REPLICATE |PARTITIONED|
+ exchange
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2])
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/max-from-terms.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/max-from-terms.plan
new file mode 100644
index 0000000..db08abc
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results_cbo/joins/max-from-terms.plan
@@ -0,0 +1,128 @@
+distribute result [$$91] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+-- DISTRIBUTE_RESULT |UNPARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ONE_TO_ONE_EXCHANGE |UNPARTITIONED|
+ assign [$$91] <- [{"$1": $$99}] project: [$$91] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ASSIGN |UNPARTITIONED|
+ aggregate [$$99] <- [agg-sql-sum($$101)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- AGGREGATE |UNPARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- RANDOM_MERGE_EXCHANGE |PARTITIONED|
+ aggregate [$$101] <- [agg-sql-count(1)] [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- AGGREGATE |PARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (eq($$92, $$98)) [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- HYBRID_HASH_JOIN [$$92][$$98] |PARTITIONED|
+ exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 6.2500250004499976E16]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ project ([$$92]) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 6.2500250004499976E16]
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 0.0, total-cost: 6.2500250004499976E16]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (eq($$93, $$92)) [cardinality: 9.223372036854776E16, doc-size: -3.0, op-cost: 6.2500125001E16, total-cost: 6.2500250004499976E16]
+ -- HYBRID_HASH_JOIN [$$93][$$92] |PARTITIONED|
+ exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.2500199998474E11]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ project ([$$93]) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.2500199998474E11]
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange [cardinality: 5.0E11, doc-size: -2.0, op-cost: 0.0, total-cost: 1.2500199998474E11]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ join (eq($$100, $$93)) [cardinality: 5.0E11, doc-size: -2.0, op-cost: 1.250005E11, total-cost: 1.2500199998474E11]
+ -- HYBRID_HASH_JOIN [$$100][$$93] |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$100] <- [$$93] project: [$$100] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- BROADCAST_EXCHANGE |PARTITIONED|
+ assign [$$92] <- [$$93] project: [$$92] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$98] <- [$$93] project: [$$98] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- HASH_PARTITION_EXCHANGE [$$93] |PARTITIONED|
+ replicate [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- REPLICATE |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ assign [$$93] <- [$$t2.getField("x")] project: [$$93] [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ASSIGN |PARTITIONED|
+ project ([$$t2]) [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- STREAM_PROJECT |PARTITIONED|
+ exchange [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ data-scan []<-[$$95, $$t2] <- test.ds [cardinality: 1000000.0, doc-size: -1.0, op-cost: 0.0, total-cost: 499992.37]
+ -- DATASOURCE_SCAN |PARTITIONED|
+ exchange [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- ONE_TO_ONE_EXCHANGE |PARTITIONED|
+ empty-tuple-source [cardinality: 0.0, doc-size: 0.0, op-cost: 0.0, total-cost: 0.0]
+ -- EMPTY_TUPLE_SOURCE |PARTITIONED|
--
To view, visit https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/21608?usp=email
To unsubscribe, or for help writing mail filters, visit https://asterix-gerrit.ics.uci.edu/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Change-Id: Idb792d775b24fb5759cade2c764114939c502b06
Gerrit-Change-Number: 21608
Gerrit-PatchSet: 1
Gerrit-Owner: Rithwik Koul <ri...@couchbase.com>