add simple optimization

This commit is contained in:
Nikita Vasilev 2021-01-03 13:24:09 +03:00
parent 48050a3ed4
commit 1d5b62cc18
5 changed files with 72 additions and 1 deletions

View File

@ -63,7 +63,7 @@ add_subdirectory (Server)
set(dbms_headers)
set(dbms_sources)
set(dbms_sources Interpreters/ConstraintMatcherVisitor.cpp Interpreters/ConstraintMatcherVisitor.h)
add_headers_and_sources(clickhouse_common_io Common)
add_headers_and_sources(clickhouse_common_io Common/HashTable)

View File

@ -378,6 +378,7 @@ class IColumn;
M(Bool, optimize_if_chain_to_multiif, false, "Replace if(cond1, then1, if(cond2, ...)) chains to multiIf. Currently it's not beneficial for numeric types.", 0) \
M(Bool, optimize_if_transform_strings_to_enum, false, "Replaces string-type arguments in If and Transform to enum. Disabled by default cause it could make inconsistent change in distributed query that would lead to its fail.", 0) \
M(Bool, optimize_monotonous_functions_in_order_by, true, "Replace monotonous function with its argument in ORDER BY", 0) \
M(Bool, optimize_using_constraints, true, "Use constraints for query optimization", 0) \
M(Bool, allow_experimental_alter_materialized_view_structure, false, "Allow atomic alter on Materialized views. Work in progress.", 0) \
M(Bool, enable_early_constant_folding, true, "Enable query optimization where we analyze function and subqueries results and rewrite query if there're constants there", 0) \
M(Bool, deduplicate_blocks_in_dependent_materialized_views, false, "Should deduplicate blocks for materialized views if the block is not a duplicate for the table. Use true to always deduplicate in dependent tables.", 0) \

View File

@ -0,0 +1 @@
#include "ConstraintMatcherVisitor.h"

View File

@ -0,0 +1,48 @@
#pragma once
#include <Interpreters/InDepthNodeVisitor.h>
#include <Parsers/ASTFunction.h>
#include <Parsers/ASTSubquery.h>
#include <Parsers/ASTLiteral.h>
#include <Parsers/ASTTablesInSelectQuery.h>
#include <Parsers/ASTIdentifier.h>
#include <Parsers/IAST.h>
#include <Common/typeid_cast.h>
namespace DB
{
/// recursive traversal and check for optimizeGroupByFunctionKeys
struct ConstraintMatcher
{
struct Data
{
std::unordered_map<UInt64, std::vector<ASTPtr>> constraints;
};
using Visitor = InDepthNodeVisitor<ConstraintMatcher, true>;
static bool needChildVisit(const ASTPtr & node, const ASTPtr &) { return (node->as<ASTFunction>()) && (node->as<ASTExpressionList>()); }
static bool alwaysTrue(const ASTPtr & node, Data & data) {
const auto it = data.constraints.find(node->getTreeHash().second);
if (it != std::end(data.constraints)) {
for (const auto & ast : it->second) {
if (node->getColumnName() == ast->getColumnName()) {
return true;
}
}
}
return false;
}
static void visit(ASTPtr & ast, Data & data)
{
if (alwaysTrue(ast, data)) {
ast = std::make_shared<ASTLiteral>(1);
}
}
};
using ConstraintMatcherVisitor = InDepthNodeVisitor<ConstraintMatcher, true>;
}

View File

@ -3,6 +3,7 @@
#include <Interpreters/TreeOptimizer.h>
#include <Interpreters/OptimizeIfChains.h>
#include <Interpreters/OptimizeIfWithConstantConditionVisitor.h>
#include <Interpreters/ConstraintMatcherVisitor.h>
#include <Interpreters/ArithmeticOperationsInAgrFuncOptimize.h>
#include <Interpreters/DuplicateOrderByVisitor.h>
#include <Interpreters/GroupByFunctionKeysVisitor.h>
@ -506,6 +507,20 @@ void optimizeLimitBy(const ASTSelectQuery * select_query)
elems = std::move(unique_elems);
}
void optimizeWithConstraints(ASTPtr & query, const NameSet & /* source_columns_set */,
const std::vector<TableWithColumnNamesAndTypes> & /* tables_with_columns */,
const StorageMetadataPtr & metadata_snapshot)
{
ConstraintMatcherVisitor::Data constraint_data;
for (const auto & constraint : metadata_snapshot->getConstraints().constraints)
{
constraint_data.constraints[constraint->getTreeHash().second].push_back(constraint);
}
ConstraintMatcherVisitor(constraint_data).visit(query);
}
/// Remove duplicated columns from USING(...).
void optimizeUsing(const ASTSelectQuery * select_query)
{
@ -597,6 +612,12 @@ void TreeOptimizer::apply(ASTPtr & query, Aliases & aliases, const NameSet & sou
/// Push the predicate expression down to the subqueries.
rewrite_subqueries = PredicateExpressionsOptimizer(context, tables_with_columns, settings).optimize(*select_query);
if (settings.optimize_using_constraints)
{
optimizeWithConstraints(select_query->refWhere(), source_columns_set, tables_with_columns, metadata_snapshot);
optimizeWithConstraints(select_query->refPrewhere(), source_columns_set, tables_with_columns, metadata_snapshot);
}
/// GROUP BY injective function elimination.
optimizeGroupBy(select_query, source_columns_set, context);