Yingyi Bu has submitted this change and it was merged. Change subject: Fix query plans for constant aggregates. ......................................................................
Fix query plans for constant aggregates. - Fixes for both global aggregates and group-by aggregates. - Allow optimizer tests to test sql++ queries. Change-Id: I8c2b9f4d566e62d56efe155554a317ea333420a6 Reviewed-on: https://asterix-gerrit.ics.uci.edu/876 Reviewed-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Reviewed-by: Till Westmann <ti...@apache.org> --- M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/base/RuleCollections.java M asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java M asterixdb/asterix-app/src/test/java/org/apache/asterix/test/optimizer/OptimizerTest.java A asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-agg.sqlpp A asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-gby-agg.sqlpp A asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-agg.plan A asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan 7 files changed, 189 insertions(+), 18 deletions(-) Approvals: Till Westmann: Looks good to me, approved Jenkins: Looks good to me, but someone else must approve; Verified 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 814c570..03ea289 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 @@ -154,7 +154,6 @@ normalization.add(new ExtractGbyExpressionsRule()); normalization.add(new ExtractDistinctByExpressionsRule()); normalization.add(new ExtractOrderExpressionsRule()); - normalization.add(new AsterixMoveFreeVariableOperatorOutOfSubplanRule()); // IntroduceStaticTypeCastRule should go before // IntroduceDynamicTypeCastRule to @@ -205,6 +204,9 @@ condPushDownAndJoinInference.add(new PushSubplanIntoGroupByRule()); condPushDownAndJoinInference.add(new NestedSubplanToJoinRule()); condPushDownAndJoinInference.add(new EliminateSubplanWithInputCardinalityOneRule()); + // The following rule should be fired after PushAggregateIntoGroupbyRule because + // pulling invariants out of a subplan will make PushAggregateIntoGroupby harder. + condPushDownAndJoinInference.add(new AsterixMoveFreeVariableOperatorOutOfSubplanRule()); return condPushDownAndJoinInference; } diff --git a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java index e5ffa2e..29d8532 100644 --- a/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java +++ b/asterixdb/asterix-algebra/src/main/java/org/apache/asterix/optimizer/rules/RemoveRedundantListifyRule.java @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.apache.asterix.lang.common.util.FunctionUtil; @@ -155,11 +156,28 @@ if (varUsedAbove.contains(unnestedVar)) { return false; } + Mutable<ILogicalOperator> aggregateParentRef = opRef; + AbstractLogicalOperator r = op1; + boolean metAggregate = false; + while (r.getInputs().size() == 1) { + aggregateParentRef = r.getInputs().get(0); + r = (AbstractLogicalOperator) aggregateParentRef.getValue(); + if (r.getOperatorTag() == LogicalOperatorTag.ASSIGN) { + AssignOperator assign = (AssignOperator) r; + List<LogicalVariable> variables = assign.getVariables(); + // The assign operator doesn't produce any variable that is used by the unnest. + if (variables.contains(unnestedVar)) { + return false; + } + } else { + if (r.getOperatorTag() == LogicalOperatorTag.AGGREGATE) { + metAggregate = true; + } + break; + } + } - Mutable<ILogicalOperator> opRef2 = op1.getInputs().get(0); - AbstractLogicalOperator r = (AbstractLogicalOperator) opRef2.getValue(); - - if (r.getOperatorTag() != LogicalOperatorTag.AGGREGATE) { + if (!metAggregate) { return false; } AggregateOperator agg = (AggregateOperator) r; @@ -185,9 +203,9 @@ } LogicalVariable paramVar = ((VariableReferenceExpression) arg0).getVariableReference(); - ArrayList<LogicalVariable> assgnVars = new ArrayList<LogicalVariable>(1); + List<LogicalVariable> assgnVars = new ArrayList<>(1); assgnVars.add(unnest1.getVariable()); - ArrayList<Mutable<ILogicalExpression>> assgnExprs = new ArrayList<Mutable<ILogicalExpression>>(1); + List<Mutable<ILogicalExpression>> assgnExprs = new ArrayList<>(1); assgnExprs.add(new MutableObject<ILogicalExpression>(new VariableReferenceExpression(paramVar))); AssignOperator assign = new AssignOperator(assgnVars, assgnExprs); assign.getInputs().add(agg.getInputs().get(0)); @@ -195,20 +213,22 @@ LogicalVariable posVar = unnest1.getPositionalVariable(); if (posVar == null) { - opRef.setValue(assign); + // Removes the aggregate operator. + aggregateParentRef.setValue(assign); } else { - ArrayList<LogicalVariable> raggVars = new ArrayList<LogicalVariable>(1); + List<LogicalVariable> raggVars = new ArrayList<>(1); raggVars.add(posVar); - ArrayList<Mutable<ILogicalExpression>> rAggExprs = new ArrayList<Mutable<ILogicalExpression>>(1); + List<Mutable<ILogicalExpression>> rAggExprs = new ArrayList<>(1); StatefulFunctionCallExpression tidFun = new StatefulFunctionCallExpression( FunctionUtil.getFunctionInfo(AsterixBuiltinFunctions.TID), UnpartitionedPropertyComputer.INSTANCE); rAggExprs.add(new MutableObject<ILogicalExpression>(tidFun)); RunningAggregateOperator rAgg = new RunningAggregateOperator(raggVars, rAggExprs); rAgg.getInputs().add(new MutableObject<ILogicalOperator>(assign)); - opRef.setValue(rAgg); + aggregateParentRef.setValue(rAgg); context.computeAndSetTypeEnvironmentForOperator(rAgg); } - + // Removes the unnest operator. + opRef.setValue(unnest1.getInputs().get(0).getValue()); return true; } @@ -243,6 +263,7 @@ if (agg.getInputs().size() == 0) { return false; } + AbstractLogicalOperator op2 = (AbstractLogicalOperator) agg.getInputs().get(0).getValue(); if (op2.getOperatorTag() != LogicalOperatorTag.UNNEST) { return false; @@ -266,7 +287,7 @@ return false; } - ArrayList<LogicalVariable> assgnVars = new ArrayList<LogicalVariable>(1); + List<LogicalVariable> assgnVars = new ArrayList<>(1); assgnVars.add(aggVar); AssignOperator assign = new AssignOperator(assgnVars, scanFunc.getArguments()); assign.getInputs().add(unnest.getInputs().get(0)); diff --git a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/optimizer/OptimizerTest.java b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/optimizer/OptimizerTest.java index 193e0aa..d0be428 100644 --- a/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/optimizer/OptimizerTest.java +++ b/asterixdb/asterix-app/src/test/java/org/apache/asterix/test/optimizer/OptimizerTest.java @@ -34,11 +34,13 @@ import org.apache.asterix.common.exceptions.AsterixException; import org.apache.asterix.compiler.provider.AqlCompilationProvider; import org.apache.asterix.compiler.provider.ILangCompilationProvider; +import org.apache.asterix.compiler.provider.SqlppCompilationProvider; import org.apache.asterix.external.util.ExternalDataConstants; import org.apache.asterix.external.util.IdentitiyResolverFactory; import org.apache.asterix.test.base.AsterixTestHelper; import org.apache.asterix.test.common.TestHelper; import org.apache.asterix.test.runtime.HDFSCluster; +import org.apache.hyracks.api.client.IHyracksClientConnection; import org.junit.AfterClass; import org.junit.Assume; import org.junit.BeforeClass; @@ -54,7 +56,8 @@ private static final Logger LOGGER = Logger.getLogger(OptimizerTest.class.getName()); private static final String SEPARATOR = File.separator; - private static final String EXTENSION_QUERY = "aql"; + private static final String EXTENSION_AQL = "aql"; + private static final String EXTENSION_SQLPP = "sqlpp"; private static final String EXTENSION_RESULT = "plan"; private static final String FILENAME_IGNORE = "ignore.txt"; private static final String FILENAME_ONLY = "only.txt"; @@ -67,7 +70,8 @@ private static final ArrayList<String> ignore = AsterixTestHelper.readFile(FILENAME_IGNORE, PATH_BASE); private static final ArrayList<String> only = AsterixTestHelper.readFile(FILENAME_ONLY, PATH_BASE); private static final String TEST_CONFIG_FILE_NAME = "asterix-build-configuration.xml"; - private static final ILangCompilationProvider compilationProvider = new AqlCompilationProvider(); + private static final ILangCompilationProvider aqlCompilationProvider = new AqlCompilationProvider(); + private static final ILangCompilationProvider sqlppCompilationProvider = new SqlppCompilationProvider(); @BeforeClass public static void setUp() throws Exception { @@ -104,7 +108,7 @@ suiteBuildPerFile(innerfile, testArgs, subdir); } } - if (file.isFile() && file.getName().endsWith(EXTENSION_QUERY)) { + if (file.isFile() && (file.getName().endsWith(EXTENSION_AQL) || file.getName().endsWith(EXTENSION_SQLPP))) { String resultFileName = AsterixTestHelper.extToResExt(file.getName(), EXTENSION_RESULT); File expectedFile = new File(PATH_EXPECTED + path + resultFileName); File actualFile = new File(PATH_ACTUAL + SEPARATOR + path + resultFileName); @@ -162,8 +166,10 @@ actualFile.getParentFile().mkdirs(); PrintWriter plan = new PrintWriter(actualFile); - AsterixJavaClient asterix = new AsterixJavaClient( - AsterixHyracksIntegrationUtil.getHyracksClientConnection(), query, plan, compilationProvider); + ILangCompilationProvider provider = queryFile.getName().endsWith("aql") ? aqlCompilationProvider + : sqlppCompilationProvider; + IHyracksClientConnection hcc = AsterixHyracksIntegrationUtil.getHyracksClientConnection(); + AsterixJavaClient asterix = new AsterixJavaClient(hcc, query, plan, provider); try { asterix.compile(true, false, false, true, true, false, false); } catch (AsterixException e) { diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-agg.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-agg.sqlpp new file mode 100644 index 0000000..a3f8ea1 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-agg.sqlpp @@ -0,0 +1,52 @@ +/* + * 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. + */ + +drop database TinySocial if exists; +create database TinySocial; + +use TinySocial; + + +create type TinySocial.TwitterUserType as +{ + "screen-name" : string +} + +create type TinySocial.TweetMessageType as { + tweetid : string +} + +create type TinySocial.FacebookUserType as + open { + id : int64 +} + +create type TinySocial.FacebookMessageType as + open { + "message-id" : int64 +} + +create table FacebookUsers(FacebookUserType) primary key id; +create table FacebookMessages(FacebookMessageType) primary key "message-id"; +create table TwitterUsers(TwitterUserType) primary key "screen-name"; +create table TweetMessages(TweetMessageType) primary key tweetid hints ("CARDINALITY"="100"); + + +SELECT COUNT(1) count +FROM FacebookUsers u; diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-gby-agg.sqlpp b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-gby-agg.sqlpp new file mode 100644 index 0000000..dcd770e --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/queries/aggregate/constant-gby-agg.sqlpp @@ -0,0 +1,53 @@ +/* + * 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. + */ + +drop database TinySocial if exists; +create database TinySocial; + +use TinySocial; + + +create type TinySocial.TwitterUserType as +{ + "screen-name" : string +} + +create type TinySocial.TweetMessageType as { + tweetid : string +} + +create type TinySocial.FacebookUserType as + open { + id : int64 +} + +create type TinySocial.FacebookMessageType as + open { + "message-id" : int64 +} + +create table FacebookUsers(FacebookUserType) primary key id; +create table FacebookMessages(FacebookMessageType) primary key "message-id"; +create table TwitterUsers(TwitterUserType) primary key "screen-name"; +create table TweetMessages(TweetMessageType) primary key tweetid hints ("CARDINALITY"="100"); + + +SELECT alias alias, COUNT(1) count +FROM FacebookUsers u +GROUP BY u.alias AS alias; diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-agg.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-agg.plan new file mode 100644 index 0000000..790a5d2 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-agg.plan @@ -0,0 +1,13 @@ +-- DISTRIBUTE_RESULT |UNPARTITIONED| + -- ONE_TO_ONE_EXCHANGE |UNPARTITIONED| + -- STREAM_PROJECT |UNPARTITIONED| + -- ASSIGN |UNPARTITIONED| + -- AGGREGATE |UNPARTITIONED| + -- RANDOM_MERGE_EXCHANGE |PARTITIONED| + -- AGGREGATE |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| diff --git a/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan b/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan new file mode 100644 index 0000000..dec5a77 --- /dev/null +++ b/asterixdb/asterix-app/src/test/resources/optimizerts/results/aggregate/constant-gby-agg.plan @@ -0,0 +1,24 @@ +-- DISTRIBUTE_RESULT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- PRE_CLUSTERED_GROUP_BY[$$29] |PARTITIONED| + { + -- AGGREGATE |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- HASH_PARTITION_MERGE_EXCHANGE MERGE:[$$29(ASC)] HASH:[$$29] |PARTITIONED| + -- SORT_GROUP_BY[$$25] |PARTITIONED| + { + -- AGGREGATE |LOCAL| + -- NESTED_TUPLE_SOURCE |LOCAL| + } + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ASSIGN |PARTITIONED| + -- STREAM_PROJECT |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- DATASOURCE_SCAN |PARTITIONED| + -- ONE_TO_ONE_EXCHANGE |PARTITIONED| + -- EMPTY_TUPLE_SOURCE |PARTITIONED| -- To view, visit https://asterix-gerrit.ics.uci.edu/876 To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings Gerrit-MessageType: merged Gerrit-Change-Id: I8c2b9f4d566e62d56efe155554a317ea333420a6 Gerrit-PatchSet: 8 Gerrit-Project: asterixdb Gerrit-Branch: master Gerrit-Owner: Yingyi Bu <buyin...@gmail.com> Gerrit-Reviewer: Jenkins <jenk...@fulliautomatix.ics.uci.edu> Gerrit-Reviewer: Till Westmann <ti...@apache.org> Gerrit-Reviewer: Yingyi Bu <buyin...@gmail.com>