Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 09BD9200B23 for ; Sun, 5 Jun 2016 01:03:35 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 0842B160A26; Sat, 4 Jun 2016 23:03:35 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 3E78C160A4E for ; Sun, 5 Jun 2016 01:03:33 +0200 (CEST) Received: (qmail 1518 invoked by uid 500); 4 Jun 2016 23:03:32 -0000 Mailing-List: contact commits-help@quickstep.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@quickstep.incubator.apache.org Delivered-To: mailing list commits@quickstep.incubator.apache.org Received: (qmail 1508 invoked by uid 99); 4 Jun 2016 23:03:32 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd3-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 04 Jun 2016 23:03:32 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd3-us-west.apache.org (ASF Mail Server at spamd3-us-west.apache.org) with ESMTP id EEB431800EC for ; Sat, 4 Jun 2016 23:03:31 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd3-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.646 X-Spam-Level: X-Spam-Status: No, score=-4.646 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-1.426] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd3-us-west.apache.org [10.40.0.10]) (amavisd-new, port 10024) with ESMTP id JzYJNKKc6m_s for ; Sat, 4 Jun 2016 23:03:24 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 6C18160D56 for ; Sat, 4 Jun 2016 23:03:19 +0000 (UTC) Received: (qmail 99470 invoked by uid 99); 4 Jun 2016 23:03:18 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 04 Jun 2016 23:03:18 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 0BE19EAD8F; Sat, 4 Jun 2016 23:03:18 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: hbdeshmukh@apache.org To: commits@quickstep.incubator.apache.org Date: Sat, 04 Jun 2016 23:03:44 -0000 Message-Id: <9fe3618c05d54eed88f2e491bd161c23@git.apache.org> In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [28/41] incubator-quickstep git commit: Added hash join order optimization for star schema queries. (#229) archived-at: Sat, 04 Jun 2016 23:03:35 -0000 Added hash join order optimization for star schema queries. (#229) Project: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/commit/0fffe505 Tree: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/tree/0fffe505 Diff: http://git-wip-us.apache.org/repos/asf/incubator-quickstep/diff/0fffe505 Branch: refs/heads/query-id-operator-workorder Commit: 0fffe5057da6b6abc1d9cdf0f7dab0accc8a0fe1 Parents: df4a05d Author: Jianqiao Zhu Authored: Thu May 19 18:19:28 2016 -0500 Committer: Zuyu Zhang Committed: Mon May 30 15:47:52 2016 -0700 ---------------------------------------------------------------------- query_optimizer/CMakeLists.txt | 2 + query_optimizer/PhysicalGenerator.cpp | 14 + query_optimizer/cost_model/CMakeLists.txt | 32 +- .../cost_model/StarSchemaSimpleCostModel.cpp | 258 ++++++++++++++++ .../cost_model/StarSchemaSimpleCostModel.hpp | 115 +++++++ query_optimizer/rules/CMakeLists.txt | 20 +- .../StarSchemaHashJoinOrderOptimization.cpp | 309 +++++++++++++++++++ .../StarSchemaHashJoinOrderOptimization.hpp | 136 ++++++++ query_optimizer/tests/CMakeLists.txt | 1 + query_optimizer/tests/OptimizerTextTest.cpp | 14 + 10 files changed, 899 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/CMakeLists.txt b/query_optimizer/CMakeLists.txt index feaecb3..aa2873e 100644 --- a/query_optimizer/CMakeLists.txt +++ b/query_optimizer/CMakeLists.txt @@ -182,10 +182,12 @@ target_link_libraries(quickstep_queryoptimizer_OptimizerTree quickstep_utility_Macros quickstep_utility_TreeStringSerializable) target_link_libraries(quickstep_queryoptimizer_PhysicalGenerator + gflags_nothreads-static quickstep_queryoptimizer_LogicalToPhysicalMapper quickstep_queryoptimizer_logical_Logical quickstep_queryoptimizer_physical_Physical quickstep_queryoptimizer_rules_PruneColumns + quickstep_queryoptimizer_rules_StarSchemaHashJoinOrderOptimization quickstep_queryoptimizer_strategy_Aggregate quickstep_queryoptimizer_strategy_Join quickstep_queryoptimizer_strategy_OneToOne http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/PhysicalGenerator.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/PhysicalGenerator.cpp b/query_optimizer/PhysicalGenerator.cpp index ee52966..662236f 100644 --- a/query_optimizer/PhysicalGenerator.cpp +++ b/query_optimizer/PhysicalGenerator.cpp @@ -1,6 +1,8 @@ /** * Copyright 2011-2015 Quickstep Technologies LLC. * Copyright 2015 Pivotal Software, Inc. + * Copyright 2016, Quickstep Research Group, Computer Sciences Department, + * University of Wisconsin—Madison. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,17 +27,26 @@ #include "query_optimizer/logical/Logical.hpp" #include "query_optimizer/physical/Physical.hpp" #include "query_optimizer/rules/PruneColumns.hpp" +#include "query_optimizer/rules/StarSchemaHashJoinOrderOptimization.hpp" #include "query_optimizer/strategy/Aggregate.hpp" #include "query_optimizer/strategy/Join.hpp" #include "query_optimizer/strategy/OneToOne.hpp" #include "query_optimizer/strategy/Selection.hpp" #include "query_optimizer/strategy/Strategy.hpp" +#include "gflags/gflags.h" + #include "glog/logging.h" namespace quickstep { namespace optimizer { +DEFINE_bool(reorder_hash_joins, true, + "If true, apply hash join order optimization to each group of hash " + "joins. The optimization applies a greedy algorithm to favor smaller " + "cardinality and selective tables to be joined first, which is suitable " + "for queries on star-schema tables"); + namespace L = ::quickstep::optimizer::logical; namespace P = ::quickstep::optimizer::physical; namespace S = ::quickstep::optimizer::strategy; @@ -77,6 +88,9 @@ P::PhysicalPtr PhysicalGenerator::generateInitialPlan( P::PhysicalPtr PhysicalGenerator::optimizePlan() { std::vector>> rules; + if (FLAGS_reorder_hash_joins) { + rules.emplace_back(new StarSchemaHashJoinOrderOptimization()); + } rules.emplace_back(new PruneColumns()); for (std::unique_ptr> &rule : rules) { http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/cost_model/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/cost_model/CMakeLists.txt b/query_optimizer/cost_model/CMakeLists.txt index 6697d52..6bf5240 100644 --- a/query_optimizer/cost_model/CMakeLists.txt +++ b/query_optimizer/cost_model/CMakeLists.txt @@ -1,5 +1,7 @@ # Copyright 2011-2015 Quickstep Technologies LLC. # Copyright 2015 Pivotal Software, Inc. +# Copyright 2016, Quickstep Research Group, Computer Sciences Department, +# University of Wisconsin—Madison. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -16,6 +18,9 @@ # Declare micro-libs: add_library(quickstep_queryoptimizer_costmodel_CostModel ../../empty_src.cpp CostModel.hpp) add_library(quickstep_queryoptimizer_costmodel_SimpleCostModel SimpleCostModel.cpp SimpleCostModel.hpp) +add_library(quickstep_queryoptimizer_costmodel_StarSchemaSimpleCostModel + StarSchemaSimpleCostModel.cpp + StarSchemaSimpleCostModel.hpp) # Link dependencies: target_link_libraries(quickstep_queryoptimizer_costmodel_CostModel @@ -36,9 +41,34 @@ target_link_libraries(quickstep_queryoptimizer_costmodel_SimpleCostModel quickstep_queryoptimizer_physical_TableReference quickstep_queryoptimizer_physical_TopLevelPlan quickstep_utility_Macros) +target_link_libraries(quickstep_queryoptimizer_costmodel_StarSchemaSimpleCostModel + glog + quickstep_catalog_CatalogRelation + quickstep_queryoptimizer_costmodel_CostModel + quickstep_queryoptimizer_expressions_AttributeReference + quickstep_queryoptimizer_expressions_ComparisonExpression + quickstep_queryoptimizer_expressions_ExprId + quickstep_queryoptimizer_expressions_ExpressionType + quickstep_queryoptimizer_expressions_LogicalAnd + quickstep_queryoptimizer_expressions_LogicalOr + quickstep_queryoptimizer_expressions_PatternMatcher + quickstep_queryoptimizer_expressions_Predicate + quickstep_queryoptimizer_physical_Aggregate + quickstep_queryoptimizer_physical_HashJoin + quickstep_queryoptimizer_physical_NestedLoopsJoin + quickstep_queryoptimizer_physical_Physical + quickstep_queryoptimizer_physical_PhysicalType + quickstep_queryoptimizer_physical_Selection + quickstep_queryoptimizer_physical_SharedSubplanReference + quickstep_queryoptimizer_physical_Sort + quickstep_queryoptimizer_physical_TableGenerator + quickstep_queryoptimizer_physical_TableReference + quickstep_queryoptimizer_physical_TopLevelPlan + quickstep_utility_Macros) # Module all-in-one library: add_library(quickstep_queryoptimizer_costmodel ../../empty_src.cpp CostModelModule.hpp) target_link_libraries(quickstep_queryoptimizer_costmodel quickstep_queryoptimizer_costmodel_CostModel - quickstep_queryoptimizer_costmodel_SimpleCostModel) + quickstep_queryoptimizer_costmodel_SimpleCostModel + quickstep_queryoptimizer_costmodel_StarSchemaSimpleCostModel) http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/cost_model/StarSchemaSimpleCostModel.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/cost_model/StarSchemaSimpleCostModel.cpp b/query_optimizer/cost_model/StarSchemaSimpleCostModel.cpp new file mode 100644 index 0000000..eb9fcc1 --- /dev/null +++ b/query_optimizer/cost_model/StarSchemaSimpleCostModel.cpp @@ -0,0 +1,258 @@ +/** + * Copyright 2016, Quickstep Research Group, Computer Sciences Department, + * University of Wisconsin—Madison. + * + * Licensed 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. + **/ + +#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp" + +#include +#include +#include +#include + +#include "catalog/CatalogRelation.hpp" +#include "query_optimizer/expressions/AttributeReference.hpp" +#include "query_optimizer/expressions/ComparisonExpression.hpp" +#include "query_optimizer/expressions/ExprId.hpp" +#include "query_optimizer/expressions/ExpressionType.hpp" +#include "query_optimizer/expressions/LogicalAnd.hpp" +#include "query_optimizer/expressions/LogicalOr.hpp" +#include "query_optimizer/expressions/Predicate.hpp" +#include "query_optimizer/expressions/PatternMatcher.hpp" +#include "query_optimizer/physical/Aggregate.hpp" +#include "query_optimizer/physical/NestedLoopsJoin.hpp" +#include "query_optimizer/physical/HashJoin.hpp" +#include "query_optimizer/physical/Physical.hpp" +#include "query_optimizer/physical/PhysicalType.hpp" +#include "query_optimizer/physical/Selection.hpp" +#include "query_optimizer/physical/SharedSubplanReference.hpp" +#include "query_optimizer/physical/Sort.hpp" +#include "query_optimizer/physical/TableGenerator.hpp" +#include "query_optimizer/physical/TableReference.hpp" +#include "query_optimizer/physical/TopLevelPlan.hpp" + +#include "glog/logging.h" + +namespace quickstep { +namespace optimizer { +namespace cost { + +namespace E = ::quickstep::optimizer::expressions; +namespace P = ::quickstep::optimizer::physical; + +std::size_t StarSchemaSimpleCostModel::estimateCardinality( + const P::PhysicalPtr &physical_plan) { + switch (physical_plan->getPhysicalType()) { + case P::PhysicalType::kTopLevelPlan: + return estimateCardinalityForTopLevelPlan( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kTableReference: + return estimateCardinalityForTableReference( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kSelection: + return estimateCardinalityForSelection( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kTableGenerator: + return estimateCardinalityForTableGenerator( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kHashJoin: + return estimateCardinalityForHashJoin( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kNestedLoopsJoin: + return estimateCardinalityForNestedLoopsJoin( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kAggregate: + return estimateCardinalityForAggregate( + std::static_pointer_cast(physical_plan)); + case P::PhysicalType::kSharedSubplanReference: { + const P::SharedSubplanReferencePtr shared_subplan_reference = + std::static_pointer_cast(physical_plan); + return estimateCardinality( + shared_subplans_[shared_subplan_reference->subplan_id()]); + } + case P::PhysicalType::kSort: + return estimateCardinality( + std::static_pointer_cast(physical_plan)->input()); + default: + LOG(FATAL) << "Unsupported physical plan:" << physical_plan->toString(); + } +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForTopLevelPlan( + const P::TopLevelPlanPtr &physical_plan) { + return estimateCardinality(physical_plan->plan()); +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForTableReference( + const P::TableReferencePtr &physical_plan) { + std::size_t num_tuples = physical_plan->relation()->getStatistics().getNumTuples(); + if (num_tuples == 0) { + num_tuples = physical_plan->relation()->estimateTupleCardinality(); + } + return num_tuples; +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForSelection( + const P::SelectionPtr &physical_plan) { + double selectivity = estimateSelectivityForSelection(physical_plan); + return std::max(static_cast(estimateCardinality(physical_plan->input()) * selectivity), + static_cast(1)); +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForTableGenerator( + const P::TableGeneratorPtr &physical_plan) { + return physical_plan->generator_function_handle()->getEstimatedCardinality(); +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForHashJoin( + const P::HashJoinPtr &physical_plan) { + std::size_t left_cardinality = estimateCardinality(physical_plan->left()); + std::size_t right_cardinality = estimateCardinality(physical_plan->right()); + double left_selectivity = estimateSelectivity(physical_plan->left()); + double right_selectivity = estimateSelectivity(physical_plan->right()); + return std::max(static_cast(left_cardinality * right_selectivity) + 1, + static_cast(right_cardinality * left_selectivity) + 1); +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForNestedLoopsJoin( + const P::NestedLoopsJoinPtr &physical_plan) { + return std::max(estimateCardinality(physical_plan->left()), + estimateCardinality(physical_plan->right())); +} + +std::size_t StarSchemaSimpleCostModel::estimateCardinalityForAggregate( + const P::AggregatePtr &physical_plan) { + if (physical_plan->grouping_expressions().empty()) { + return 1; + } + return std::max(static_cast(1), + estimateCardinality(physical_plan->input()) / 10); +} + +double StarSchemaSimpleCostModel::estimateSelectivity( + const physical::PhysicalPtr &physical_plan) { + switch (physical_plan->getPhysicalType()) { + case P::PhysicalType::kSelection: { + return estimateSelectivityForSelection( + std::static_pointer_cast(physical_plan)); + } + case P::PhysicalType::kHashJoin: { + const P::HashJoinPtr &hash_join = + std::static_pointer_cast(physical_plan); + return std::min(estimateSelectivity(hash_join->left()), + estimateSelectivity(hash_join->right())); + } + case P::PhysicalType::kNestedLoopsJoin: { + const P::NestedLoopsJoinPtr &nested_loop_join = + std::static_pointer_cast(physical_plan); + return std::min(estimateSelectivity(nested_loop_join->left()), + estimateSelectivity(nested_loop_join->right())); + } + case P::PhysicalType::kSharedSubplanReference: { + const P::SharedSubplanReferencePtr shared_subplan_reference = + std::static_pointer_cast(physical_plan); + return estimateSelectivity( + shared_subplans_[shared_subplan_reference->subplan_id()]); + } + default: + return 1.0; + } +} + +double StarSchemaSimpleCostModel::estimateSelectivityForSelection( + const physical::SelectionPtr &physical_plan) { + const E::PredicatePtr &filter_predicate = physical_plan->filter_predicate(); + + // If the subplan is a table reference, gather the number of distinct values + // statistics for each column (attribute). + std::unordered_map num_distinct_values_map; + if (physical_plan->input()->getPhysicalType() == P::PhysicalType::kTableReference) { + const P::TableReferencePtr &table_reference = + std::static_pointer_cast(physical_plan->input()); + const CatalogRelation &relation = *table_reference->relation(); + const std::vector &attributes = table_reference->attribute_list(); + for (std::size_t i = 0; i < attributes.size(); ++i) { + std::size_t num_distinct_values = relation.getStatistics().getNumDistinctValues(i); + if (num_distinct_values > 0) { + num_distinct_values_map[attributes[i]->id()] = num_distinct_values; + } + } + } + + return estimateSelectivityForPredicate(num_distinct_values_map, filter_predicate); +} + +double StarSchemaSimpleCostModel::estimateSelectivityForPredicate( + const std::unordered_map &num_distinct_values_map, + const expressions::PredicatePtr &filter_predicate) { + if (filter_predicate == nullptr) { + return 1.0; + } + + switch (filter_predicate->getExpressionType()) { + case E::ExpressionType::kComparisonExpression: { + // Case 1 - Number of distinct values statistics available + // Case 1.1 - Equality comparison: 1.0 / num_distinct_values + // Case 1.2 - Otherwise: 5.0 / num_distinct_values + // Case 2 - Number of distinct values statistics not available + // Case 2.1 - Equality comparison: 0.1 + // Case 2.2 - Otherwise: 0.5 + const E::ComparisonExpressionPtr &comparison_expression = + std::static_pointer_cast(filter_predicate); + E::AttributeReferencePtr attr; + if ((E::SomeAttributeReference::MatchesWithConditionalCast(comparison_expression->left(), &attr) && + E::SomeScalarLiteral::Matches(comparison_expression->right())) || + (E::SomeAttributeReference::MatchesWithConditionalCast(comparison_expression->right(), &attr) && + E::SomeScalarLiteral::Matches(comparison_expression->left()))) { + const auto it = num_distinct_values_map.find(attr->id()); + if (it != num_distinct_values_map.end() && it->second > 0) { + double unit_selectivity = 1.0 / it->second; + return comparison_expression->isEqualityComparisonPredicate() + ? unit_selectivity + : std::min(0.5, unit_selectivity * 5.0); + } + } + + return comparison_expression->isEqualityComparisonPredicate() ? 0.1 : 0.5; + } + case E::ExpressionType::kLogicalAnd: { + const E::LogicalAndPtr &logical_and = + std::static_pointer_cast(filter_predicate); + double selectivity = 1.0; + for (const auto &predicate : logical_and->operands()) { + selectivity = + std::min(selectivity, + estimateSelectivityForPredicate(num_distinct_values_map, predicate)); + } + return selectivity; + } + case E::ExpressionType::kLogicalOr: { + const E::LogicalOrPtr &logical_or = + std::static_pointer_cast(filter_predicate); + double selectivity = 0; + for (const auto &predicate : logical_or->operands()) { + selectivity += estimateSelectivityForPredicate(num_distinct_values_map, predicate); + } + return std::min(selectivity, 1.0); + } + default: + break; + } + return 1.0; +} + +} // namespace cost +} // namespace optimizer +} // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp b/query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp new file mode 100644 index 0000000..c63e55a --- /dev/null +++ b/query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp @@ -0,0 +1,115 @@ +/** + * Copyright 2016, Quickstep Research Group, Computer Sciences Department, + * University of Wisconsin—Madison. + * + * Licensed 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. + **/ + +#ifndef QUERY_OPTIMIZER_COST_MODEL_STAR_SCHEMA_SIMPLE_COST_MODEL_HPP_ +#define QUERY_OPTIMIZER_COST_MODEL_STAR_SCHEMA_SIMPLE_COST_MODEL_HPP_ + +#include +#include +#include + +#include "query_optimizer/cost_model/CostModel.hpp" +#include "query_optimizer/expressions/ExprId.hpp" +#include "query_optimizer/expressions/Predicate.hpp" +#include "query_optimizer/physical/Aggregate.hpp" +#include "query_optimizer/physical/NestedLoopsJoin.hpp" +#include "query_optimizer/physical/HashJoin.hpp" +#include "query_optimizer/physical/Physical.hpp" +#include "query_optimizer/physical/Selection.hpp" +#include "query_optimizer/physical/TableGenerator.hpp" +#include "query_optimizer/physical/TableReference.hpp" +#include "query_optimizer/physical/TopLevelPlan.hpp" +#include "utility/Macros.hpp" + +namespace quickstep { +namespace optimizer { +namespace cost { + +/** \addtogroup CostModel + * @{ + */ + +/** + * @brief A simple cost model for hash join planning. + */ +class StarSchemaSimpleCostModel : public CostModel { + public: + /** + * @brief Constructor. + */ + explicit StarSchemaSimpleCostModel(const std::vector &shared_subplans) + : shared_subplans_(shared_subplans) {} + + /** + * @brief Estimate the cardinality of a physical plan. + * + * @param physical_plan The physical plan. + * @return The estimated cardinality. + */ + std::size_t estimateCardinality( + const physical::PhysicalPtr &physical_plan) override; + + /** + * @brief Estimate the "selectivity" of a physical plan under the assumption + * that it acts as a filtered dimension table in a hash join. + * + * @param phyiscal_plan The physical plan. + * @return The estimated selectivity. + */ + double estimateSelectivity(const physical::PhysicalPtr &physical_plan); + + private: + std::size_t estimateCardinalityForTopLevelPlan( + const physical::TopLevelPlanPtr &physical_plan); + + std::size_t estimateCardinalityForTableReference( + const physical::TableReferencePtr &physical_plan); + + std::size_t estimateCardinalityForSelection( + const physical::SelectionPtr &physical_plan); + + std::size_t estimateCardinalityForTableGenerator( + const physical::TableGeneratorPtr &physical_plan); + + std::size_t estimateCardinalityForHashJoin( + const physical::HashJoinPtr &physical_plan); + + std::size_t estimateCardinalityForNestedLoopsJoin( + const physical::NestedLoopsJoinPtr &physical_plan); + + std::size_t estimateCardinalityForAggregate( + const physical::AggregatePtr &physical_plan); + + double estimateSelectivityForSelection( + const physical::SelectionPtr &physical_plan); + + double estimateSelectivityForPredicate( + const std::unordered_map &num_distinct_values_map, + const expressions::PredicatePtr &filter_predicate); + + const std::vector &shared_subplans_; + + DISALLOW_COPY_AND_ASSIGN(StarSchemaSimpleCostModel); +}; + +/** @} */ + +} // namespace cost +} // namespace optimizer +} // namespace quickstep + +#endif /* QUERY_OPTIMIZER_COST_MODEL_STAR_SCHEMA_SIMPLE_COST_MODEL_HPP_ */ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/rules/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/rules/CMakeLists.txt b/query_optimizer/rules/CMakeLists.txt index 7032af5..1990174 100644 --- a/query_optimizer/rules/CMakeLists.txt +++ b/query_optimizer/rules/CMakeLists.txt @@ -26,11 +26,14 @@ add_library(quickstep_queryoptimizer_rules_PushDownFilter PushDownFilter.cpp Pus add_library(quickstep_queryoptimizer_rules_PushDownSemiAntiJoin PushDownSemiAntiJoin.cpp PushDownSemiAntiJoin.hpp) add_library(quickstep_queryoptimizer_rules_Rule ../../empty_src.cpp Rule.hpp) add_library(quickstep_queryoptimizer_rules_RuleHelper RuleHelper.cpp RuleHelper.hpp) +add_library(quickstep_queryoptimizer_rules_StarSchemaHashJoinOrderOptimization + StarSchemaHashJoinOrderOptimization.cpp + StarSchemaHashJoinOrderOptimization.hpp) add_library(quickstep_queryoptimizer_rules_TopDownRule ../../empty_src.cpp TopDownRule.hpp) add_library(quickstep_queryoptimizer_rules_UpdateExpression UpdateExpression.cpp UpdateExpression.hpp) add_library(quickstep_queryoptimizer_rules_UnnestSubqueries UnnestSubqueries.cpp UnnestSubqueries.hpp) - + # Link dependencies: target_link_libraries(quickstep_queryoptimizer_rules_BottomUpRule glog @@ -110,6 +113,20 @@ target_link_libraries(quickstep_queryoptimizer_rules_RuleHelper quickstep_queryoptimizer_expressions_PatternMatcher quickstep_queryoptimizer_expressions_Predicate quickstep_queryoptimizer_rules_UpdateExpression) +target_link_libraries(quickstep_queryoptimizer_rules_StarSchemaHashJoinOrderOptimization + quickstep_queryoptimizer_costmodel_StarSchemaSimpleCostModel + quickstep_queryoptimizer_expressions_AttributeReference + quickstep_queryoptimizer_expressions_ExprId + quickstep_queryoptimizer_expressions_NamedExpression + quickstep_queryoptimizer_expressions_PatternMatcher + quickstep_queryoptimizer_expressions_Predicate + quickstep_queryoptimizer_physical_HashJoin + quickstep_queryoptimizer_physical_PatternMatcher + quickstep_queryoptimizer_physical_Physical + quickstep_queryoptimizer_physical_PhysicalType + quickstep_queryoptimizer_physical_TopLevelPlan + quickstep_queryoptimizer_rules_Rule + quickstep_utility_Macros) target_link_libraries(quickstep_queryoptimizer_rules_TopDownRule quickstep_queryoptimizer_rules_Rule quickstep_utility_Macros) @@ -167,6 +184,7 @@ target_link_libraries(quickstep_queryoptimizer_rules quickstep_queryoptimizer_rules_PushDownSemiAntiJoin quickstep_queryoptimizer_rules_Rule quickstep_queryoptimizer_rules_RuleHelper + quickstep_queryoptimizer_rules_StarSchemaHashJoinOrderOptimization quickstep_queryoptimizer_rules_TopDownRule quickstep_queryoptimizer_rules_UpdateExpression quickstep_queryoptimizer_rules_UnnestSubqueries) http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.cpp b/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.cpp new file mode 100644 index 0000000..9770606 --- /dev/null +++ b/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.cpp @@ -0,0 +1,309 @@ +/** + * Copyright 2016, Quickstep Research Group, Computer Sciences Department, + * University of Wisconsin—Madison. + * + * Licensed 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. + **/ + +#include "query_optimizer/rules/StarSchemaHashJoinOrderOptimization.hpp" + +#include +#include +#include +#include + +#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp" +#include "query_optimizer/expressions/AttributeReference.hpp" +#include "query_optimizer/expressions/NamedExpression.hpp" +#include "query_optimizer/expressions/PatternMatcher.hpp" +#include "query_optimizer/physical/HashJoin.hpp" +#include "query_optimizer/physical/PatternMatcher.hpp" +#include "query_optimizer/physical/Physical.hpp" +#include "query_optimizer/physical/PhysicalType.hpp" +#include "query_optimizer/physical/TopLevelPlan.hpp" + +#include "glog/logging.h" + +namespace quickstep { +namespace optimizer { + +namespace E = ::quickstep::optimizer::expressions; +namespace P = ::quickstep::optimizer::physical; + +P::PhysicalPtr StarSchemaHashJoinOrderOptimization::apply(const P::PhysicalPtr &input) { + DCHECK(input->getPhysicalType() == P::PhysicalType::kTopLevelPlan); + cost_model_.reset( + new cost::StarSchemaSimpleCostModel( + std::static_pointer_cast(input)->shared_subplans())); + + return applyInternal(input, nullptr); +} + +P::PhysicalPtr StarSchemaHashJoinOrderOptimization::applyInternal(const P::PhysicalPtr &input, + JoinGroupInfo *parent_join_group) { + P::HashJoinPtr hash_join; + const bool is_hash_inner_join = + P::SomeHashJoin::MatchesWithConditionalCast(input, &hash_join) + && hash_join->join_type() == P::HashJoin::JoinType::kInnerJoin; + + if (is_hash_inner_join) { + bool is_valid_cascading_hash_join = false; + if (hash_join->residual_predicate() == nullptr) { + is_valid_cascading_hash_join = true; + for (const E::NamedExpressionPtr expr : hash_join->project_expressions()) { + if (!E::SomeAttributeReference::Matches(expr)) { + is_valid_cascading_hash_join = false; + break; + } + } + } + + std::unique_ptr new_join_group; + JoinGroupInfo *join_group = nullptr; + if (parent_join_group == nullptr || !is_valid_cascading_hash_join) { + new_join_group.reset(new JoinGroupInfo()); + join_group = new_join_group.get(); + } else { + join_group = parent_join_group; + } + + // Gather tables into the join group. + for (const P::PhysicalPtr &child : input->children()) { + applyInternal(child, join_group); + } + + // Gather join attribute pairs. + for (std::size_t i = 0; i < hash_join->left_join_attributes().size(); ++i) { + const std::size_t left_attr_id = hash_join->left_join_attributes()[i]->id(); + const std::size_t right_attr_id = hash_join->right_join_attributes()[i]->id(); + + join_group->join_attribute_pairs.emplace_back(left_attr_id, right_attr_id); + } + + if (join_group != parent_join_group) { + // This node is the root node for a group of hash inner joins. Now plan the + // ordering of the joins. + P::PhysicalPtr output = generatePlan(*join_group, + hash_join->residual_predicate(), + hash_join->project_expressions()); + if (parent_join_group == nullptr) { + return output; + } else { + parent_join_group->tables.emplace_back(output); + return nullptr; + } + } else { + return nullptr; + } + } else { + std::vector new_children; + bool has_changed_children = false; + for (const P::PhysicalPtr &child : input->children()) { + P::PhysicalPtr new_child = applyInternal(child, nullptr); + DCHECK(new_child != nullptr); + if (child != new_child && !has_changed_children) { + has_changed_children = true; + } + new_children.push_back(new_child); + } + + P::PhysicalPtr output = + (has_changed_children ? input->copyWithNewChildren(new_children) + : input); + + if (parent_join_group == nullptr) { + return output; + } else { + parent_join_group->tables.emplace_back(output); + return nullptr; + } + } +} + +physical::PhysicalPtr StarSchemaHashJoinOrderOptimization::generatePlan( + const JoinGroupInfo &join_group, + const E::PredicatePtr &residual_predicate, + const std::vector &project_expressions) { + const std::size_t num_tables = join_group.tables.size(); + DCHECK_GE(num_tables, 2u); + + std::vector table_info_storage; + const std::vector &tables = join_group.tables; + for (std::size_t i = 0; i < join_group.tables.size(); ++i) { + table_info_storage.emplace_back( + i, + tables[i], + cost_model_->estimateCardinality(tables[i]), + cost_model_->estimateSelectivity(tables[i])); + } + + // Auxiliary mapping info. + std::unordered_map attribute_id_to_table_info_index_map; + std::unordered_map attribute_id_to_reference_map; + for (std::size_t table_idx = 0; table_idx < num_tables; ++table_idx) { + for (const E::AttributeReferencePtr &attr : + table_info_storage[table_idx].table->getOutputAttributes()) { + DCHECK(attribute_id_to_table_info_index_map.find(attr->id()) + == attribute_id_to_table_info_index_map.end()); + + attribute_id_to_table_info_index_map.emplace(attr->id(), table_idx); + attribute_id_to_reference_map.emplace(attr->id(), attr); + } + } + + // Create a join graph where tables are vertices, and add an edge between vertices + // t1 and t2 for each join predicate t1.x = t2.y + std::vector> join_graph(table_info_storage.size()); + for (const auto &attr_id_pair : join_group.join_attribute_pairs) { + DCHECK(attribute_id_to_table_info_index_map.find(attr_id_pair.first) + != attribute_id_to_table_info_index_map.end()); + DCHECK(attribute_id_to_table_info_index_map.find(attr_id_pair.second) + != attribute_id_to_table_info_index_map.end()); + + std::size_t first_table_idx = + attribute_id_to_table_info_index_map[attr_id_pair.first]; + std::size_t second_table_idx = + attribute_id_to_table_info_index_map[attr_id_pair.second]; + DCHECK_NE(first_table_idx, second_table_idx); + + table_info_storage[first_table_idx].join_attribute_pairs.emplace( + attr_id_pair.first, attr_id_pair.second); + table_info_storage[second_table_idx].join_attribute_pairs.emplace( + attr_id_pair.second, attr_id_pair.first); + + join_graph[first_table_idx].emplace(second_table_idx); + join_graph[second_table_idx].emplace(first_table_idx); + } + + std::set table_info_ordered_by_priority; + for (std::size_t i = 0; i < table_info_storage.size(); ++i) { + table_info_ordered_by_priority.emplace(&table_info_storage[i]); + } + + // Contruct hash join tree. + while (true) { + TableInfo *first_table_info = *table_info_ordered_by_priority.begin(); + table_info_ordered_by_priority.erase( + table_info_ordered_by_priority.begin()); + const std::size_t first_table_info_id = first_table_info->table_info_id; + + TableInfo *second_table_info = nullptr; + std::set::iterator second_table_info_it; + for (auto candidate_table_info_it = table_info_ordered_by_priority.begin(); + candidate_table_info_it != table_info_ordered_by_priority.end(); + ++candidate_table_info_it) { + TableInfo *candidate_table_info = *candidate_table_info_it; + const std::size_t candidate_table_info_id = candidate_table_info->table_info_id; + + if (join_graph[first_table_info_id].find(candidate_table_info_id) + == join_graph[first_table_info_id].end() && + join_graph[candidate_table_info_id].find(first_table_info_id) + == join_graph[candidate_table_info_id].end()) { + continue; + } else if (second_table_info == nullptr) { + second_table_info = candidate_table_info; + second_table_info_it = candidate_table_info_it; + } + + bool is_likely_many_to_many_join = false; + for (const auto join_attr_pair : first_table_info->join_attribute_pairs) { + if (candidate_table_info->joined_attribute_set.find(join_attr_pair.second) + != candidate_table_info->joined_attribute_set.end()) { + is_likely_many_to_many_join = true; + break; + } + } + for (const auto join_attr_pair : candidate_table_info->join_attribute_pairs) { + if (first_table_info->joined_attribute_set.find(join_attr_pair.second) + != first_table_info->joined_attribute_set.end()) { + is_likely_many_to_many_join = true; + break; + } + } + if (!is_likely_many_to_many_join) { + second_table_info = candidate_table_info; + second_table_info_it = candidate_table_info_it; + break; + } + } + DCHECK(second_table_info != nullptr); + table_info_ordered_by_priority.erase(second_table_info_it); + + const P::PhysicalPtr &left_child = first_table_info->table; + const P::PhysicalPtr &right_child = second_table_info->table; + std::vector output_attributes; + for (const E::AttributeReferencePtr &left_attr : left_child->getOutputAttributes()) { + output_attributes.emplace_back(left_attr); + } + for (const E::AttributeReferencePtr &right_attr : right_child->getOutputAttributes()) { + output_attributes.emplace_back(right_attr); + } + + std::vector left_join_attributes; + std::vector right_join_attributes; + std::unordered_set new_joined_attribute_set; + for (const auto &join_attr_pair : first_table_info->join_attribute_pairs) { + if (second_table_info->join_attribute_pairs.find(join_attr_pair.second) + != second_table_info->join_attribute_pairs.end()) { + left_join_attributes.emplace_back( + attribute_id_to_reference_map[join_attr_pair.first]); + right_join_attributes.emplace_back( + attribute_id_to_reference_map[join_attr_pair.second]); + + new_joined_attribute_set.emplace(join_attr_pair.first); + new_joined_attribute_set.emplace(join_attr_pair.second); + } + } + DCHECK_GE(left_join_attributes.size(), static_cast(1)); + + if (table_info_ordered_by_priority.size() > 0) { + P::PhysicalPtr output = + P::HashJoin::Create(left_child, + right_child, + left_join_attributes, + right_join_attributes, + nullptr, + output_attributes, + P::HashJoin::JoinType::kInnerJoin); + + second_table_info->table = output; + + // TODO(jianqiao): Cache the estimated cardinality for each plan in cost + // model to avoid duplicated estimation. + second_table_info->estimated_cardinality = cost_model_->estimateCardinality(output); + + second_table_info->join_attribute_pairs.insert(first_table_info->join_attribute_pairs.begin(), + first_table_info->join_attribute_pairs.end()); + second_table_info->joined_attribute_set.insert(first_table_info->joined_attribute_set.begin(), + first_table_info->joined_attribute_set.end()); + second_table_info->joined_attribute_set.insert(new_joined_attribute_set.begin(), + new_joined_attribute_set.end()); + table_info_ordered_by_priority.emplace(second_table_info); + + join_graph[second_table_info->table_info_id].insert(join_graph[first_table_info_id].begin(), + join_graph[first_table_info_id].end()); + + } else { + return P::HashJoin::Create(left_child, + right_child, + left_join_attributes, + right_join_attributes, + residual_predicate, + project_expressions, + P::HashJoin::JoinType::kInnerJoin); + } + } +} + +} // namespace optimizer +} // namespace quickstep http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.hpp ---------------------------------------------------------------------- diff --git a/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.hpp b/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.hpp new file mode 100644 index 0000000..deddffd --- /dev/null +++ b/query_optimizer/rules/StarSchemaHashJoinOrderOptimization.hpp @@ -0,0 +1,136 @@ +/** + * Copyright 2016, Quickstep Research Group, Computer Sciences Department, + * University of Wisconsin—Madison. + * + * Licensed 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. + **/ + +#ifndef QUICKSTEP_QUERY_OPTIMIZER_RULES_STAR_SCHEMA_HASH_JOIN_ORDER_OPTIMIZATION_HPP_ +#define QUICKSTEP_QUERY_OPTIMIZER_RULES_STAR_SCHEMA_HASH_JOIN_ORDER_OPTIMIZATION_HPP_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "query_optimizer/cost_model/StarSchemaSimpleCostModel.hpp" +#include "query_optimizer/expressions/ExprId.hpp" +#include "query_optimizer/expressions/NamedExpression.hpp" +#include "query_optimizer/expressions/Predicate.hpp" +#include "query_optimizer/physical/Physical.hpp" +#include "query_optimizer/rules/Rule.hpp" +#include "utility/Macros.hpp" + +namespace quickstep { +namespace optimizer { + +/** \addtogroup OptimizerRules + * @{ + */ + +/** + * @brief TODO + */ +class StarSchemaHashJoinOrderOptimization : public Rule { + public: + StarSchemaHashJoinOrderOptimization() {} + + ~StarSchemaHashJoinOrderOptimization() override {} + + std::string getName() const override { + return "StarSchemaHashJoinOrderOptimization"; + } + + physical::PhysicalPtr apply(const physical::PhysicalPtr &input) override; + + private: + /** + * @brief A group of tables to form a hash join tree. + */ + struct JoinGroupInfo { + std::vector tables; + std::vector> join_attribute_pairs; + }; + + /** + * @brief Auxiliary information of a table for the optimizer. + */ + struct TableInfo { + TableInfo(const std::size_t in_table_info_id, + const physical::PhysicalPtr &in_table, + const std::size_t in_estimated_cardinality, + const double in_estimated_selectivity) + : table_info_id(in_table_info_id), + table(in_table), + estimated_cardinality(in_estimated_cardinality), + estimated_selectivity(in_estimated_selectivity) { + } + + const std::size_t table_info_id; + physical::PhysicalPtr table; + std::size_t estimated_cardinality; + double estimated_selectivity; + std::unordered_multimap join_attribute_pairs; + std::unordered_set joined_attribute_set; + }; + + /** + * @brief Comparator that compares the join priorities between two tables. + */ + struct TableInfoPtrLessComparator { + inline bool operator() (const TableInfo *lhs, const TableInfo *rhs) { + bool swapped = false; + if (lhs->estimated_cardinality > rhs->estimated_cardinality) { + std::swap(lhs, rhs); + swapped = true; + } + + if (lhs->estimated_selectivity < rhs->estimated_selectivity) { + return !swapped; + } else if (lhs->estimated_cardinality < 1000u && + rhs->estimated_cardinality > 10000u && + lhs->estimated_selectivity < rhs->estimated_selectivity * 1.5) { + return !swapped; + } else if (lhs->estimated_selectivity > rhs->estimated_selectivity) { + return swapped; + } else if (lhs->estimated_cardinality != rhs->estimated_cardinality) { + return !swapped; + } else { + return swapped ^ (lhs->table < rhs->table); + } + } + }; + + physical::PhysicalPtr applyInternal(const physical::PhysicalPtr &input, + JoinGroupInfo *paret_join_group); + + physical::PhysicalPtr generatePlan( + const JoinGroupInfo &join_group_info, + const expressions::PredicatePtr &residual_predicate, + const std::vector &project_expressions); + + std::unique_ptr cost_model_; + + DISALLOW_COPY_AND_ASSIGN(StarSchemaHashJoinOrderOptimization); +}; + +/** @} */ + +} // namespace optimizer +} // namespace quickstep + +#endif /* QUICKSTEP_QUERY_OPTIMIZER_RULES_STAR_SCHEMA_HASH_JOIN_ORDER_OPTIMIZATION_HPP_ */ http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/tests/CMakeLists.txt ---------------------------------------------------------------------- diff --git a/query_optimizer/tests/CMakeLists.txt b/query_optimizer/tests/CMakeLists.txt index 5647bfd..07af404 100644 --- a/query_optimizer/tests/CMakeLists.txt +++ b/query_optimizer/tests/CMakeLists.txt @@ -132,6 +132,7 @@ target_link_libraries(quickstep_queryoptimizer_tests_ExecutionGeneratorTest tmb ${LIBS}) target_link_libraries(quickstep_queryoptimizer_tests_OptimizerTextTest + gflags_nothreads-static glog gtest gtest_main http://git-wip-us.apache.org/repos/asf/incubator-quickstep/blob/0fffe505/query_optimizer/tests/OptimizerTextTest.cpp ---------------------------------------------------------------------- diff --git a/query_optimizer/tests/OptimizerTextTest.cpp b/query_optimizer/tests/OptimizerTextTest.cpp index c35cfa3..f3c243b 100644 --- a/query_optimizer/tests/OptimizerTextTest.cpp +++ b/query_optimizer/tests/OptimizerTextTest.cpp @@ -22,8 +22,18 @@ #include "query_optimizer/tests/OptimizerTextTestRunner.hpp" #include "utility/textbased_test/TextBasedTestDriver.hpp" +#include "gflags/gflags.h" + #include "glog/logging.h" +namespace quickstep { +namespace optimizer { + +DECLARE_bool(reorder_hash_joins); + +} +} + using quickstep::TextBasedTest; QUICKSTEP_GENERATE_TEXT_TEST(OPTIMIZER_TEST); @@ -45,6 +55,10 @@ int main(int argc, char** argv) { test_driver->registerOptions( quickstep::optimizer::OptimizerTextTestRunner::kTestOptions); + // Turn off join order optimization for optimizer test since it is up to change + // and affects a large number of test cases. + quickstep::optimizer::FLAGS_reorder_hash_joins = false; + ::testing::InitGoogleTest(&argc, argv); int success = RUN_ALL_TESTS(); if (success != 0) {