mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-28 10:31:57 +00:00
Rewrite arithmetic in aggregate functions optimisation (#11899)
This commit is contained in:
parent
2ce2588770
commit
2391ac22b7
@ -363,7 +363,7 @@ struct Settings : public SettingsCollection<Settings>
|
|||||||
M(SettingBool, optimize_trivial_count_query, true, "Process trivial 'SELECT count() FROM table' query from metadata.", 0) \
|
M(SettingBool, optimize_trivial_count_query, true, "Process trivial 'SELECT count() FROM table' query from metadata.", 0) \
|
||||||
M(SettingUInt64, mutations_sync, 0, "Wait for synchronous execution of ALTER TABLE UPDATE/DELETE queries (mutations). 0 - execute asynchronously. 1 - wait current server. 2 - wait all replicas if they exist.", 0) \
|
M(SettingUInt64, mutations_sync, 0, "Wait for synchronous execution of ALTER TABLE UPDATE/DELETE queries (mutations). 0 - execute asynchronously. 1 - wait current server. 2 - wait all replicas if they exist.", 0) \
|
||||||
M(SettingBool, optimize_move_functions_out_of_any, true, "Move functions out of aggregate functions 'any', 'anyLast'.", 0) \
|
M(SettingBool, optimize_move_functions_out_of_any, true, "Move functions out of aggregate functions 'any', 'anyLast'.", 0) \
|
||||||
M(SettingBool, optimize_arithmetic_operations_in_aggregate_functions, false, "Move arithmetic operations out of aggregation functions", 0) \
|
M(SettingBool, optimize_arithmetic_operations_in_aggregate_functions, true, "Move arithmetic operations out of aggregation functions", 0) \
|
||||||
M(SettingBool, optimize_duplicate_order_by_and_distinct, true, "Remove duplicate ORDER BY and DISTINCT if it's possible", 0) \
|
M(SettingBool, optimize_duplicate_order_by_and_distinct, true, "Remove duplicate ORDER BY and DISTINCT if it's possible", 0) \
|
||||||
M(SettingBool, optimize_if_chain_to_miltiif, false, "Replace if(cond1, then1, if(cond2, ...)) chains to multiIf. Currently it's not beneficial for numeric types.", 0) \
|
M(SettingBool, optimize_if_chain_to_miltiif, false, "Replace if(cond1, then1, if(cond2, ...)) chains to multiIf. Currently it's not beneficial for numeric types.", 0) \
|
||||||
M(SettingBool, allow_experimental_alter_materialized_view_structure, false, "Allow atomic alter on Materialized views. Work in progress.", 0) \
|
M(SettingBool, allow_experimental_alter_materialized_view_structure, false, "Allow atomic alter on Materialized views. Work in progress.", 0) \
|
||||||
|
@ -1,327 +1,159 @@
|
|||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#include <Common/typeid_cast.h>
|
#include <Common/typeid_cast.h>
|
||||||
#include <Parsers/ASTLiteral.h>
|
#include <Parsers/ASTLiteral.h>
|
||||||
#include <Parsers/ASTFunction.h>
|
#include <Parsers/ASTFunction.h>
|
||||||
#include <Interpreters/ArithmeticOperationsInAgrFuncOptimize.h>
|
#include <Parsers/ASTSubquery.h>
|
||||||
#include <IO/WriteHelpers.h>
|
|
||||||
#include <Parsers/ASTTablesInSelectQuery.h>
|
#include <Parsers/ASTTablesInSelectQuery.h>
|
||||||
|
#include <Interpreters/ArithmeticOperationsInAgrFuncOptimize.h>
|
||||||
|
|
||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace ErrorCodes
|
namespace ErrorCodes
|
||||||
{
|
{
|
||||||
extern const int LOGICAL_ERROR;
|
extern const int BAD_TYPE_OF_FIELD;
|
||||||
extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH;
|
|
||||||
extern const int UNEXPECTED_AST_STRUCTURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
constexpr const char * min = "min";
|
const ASTFunction * getInternalFunction(const ASTFunction & func)
|
||||||
constexpr const char * max = "max";
|
|
||||||
constexpr const char * mul = "multiply";
|
|
||||||
constexpr const char * plus = "plus";
|
|
||||||
constexpr const char * sum = "sum";
|
|
||||||
|
|
||||||
|
|
||||||
bool isConstantField(const Field & field)
|
|
||||||
{
|
{
|
||||||
return field.getType() == Field::Types::Int64 ||
|
if (func.arguments->children.size() == 1)
|
||||||
field.getType() == Field::Types::UInt64 ||
|
return func.arguments->children[0]->as<ASTFunction>();
|
||||||
field.getType() == Field::Types::Int128 ||
|
return nullptr;
|
||||||
field.getType() == Field::Types::UInt128;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool onlyConstsInside(const ASTFunction * func_node)
|
ASTPtr exchangeExtractFirstArgument(const String & func_name, const ASTFunction & child_func)
|
||||||
{
|
{
|
||||||
return !(func_node->arguments->children[0]->as<ASTFunction>()) &&
|
ASTs new_child_args;
|
||||||
(func_node->arguments->children.size() == 2 &&
|
new_child_args.push_back(child_func.arguments->children[1]);
|
||||||
!(func_node->arguments->children[1]->as<ASTFunction>()));
|
|
||||||
|
auto new_child = makeASTFunction(func_name, new_child_args);
|
||||||
|
|
||||||
|
ASTs new_args;
|
||||||
|
new_args.push_back(child_func.arguments->children[0]);
|
||||||
|
new_args.push_back(new_child);
|
||||||
|
|
||||||
|
return makeASTFunction(child_func.name, new_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool inappropriateNameInside(const ASTFunction * func_node, const char * inter_func_name)
|
ASTPtr exchangeExtractSecondArgument(const String & func_name, const ASTFunction & child_func)
|
||||||
{
|
{
|
||||||
return (func_node->arguments->children[0]->as<ASTFunction>() &&
|
ASTs new_child_args;
|
||||||
strcmp(inter_func_name, func_node->arguments->children[0]->as<ASTFunction>()->name.c_str()) != 0) ||
|
new_child_args.push_back(child_func.arguments->children[0]);
|
||||||
(func_node->arguments->children.size() == 2 &&
|
|
||||||
func_node->arguments->children[1]->as<ASTFunction>() &&
|
auto new_child = makeASTFunction(func_name, new_child_args);
|
||||||
strcmp(inter_func_name, func_node->arguments->children[1]->as<ASTFunction>()->name.c_str()) != 0);
|
|
||||||
|
ASTs new_args;
|
||||||
|
new_args.push_back(new_child);
|
||||||
|
new_args.push_back(child_func.arguments->children[1]);
|
||||||
|
|
||||||
|
return makeASTFunction(child_func.name, new_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isInappropriate(const ASTPtr & node, const char * inter_func_name)
|
Field zeroField(const Field & value)
|
||||||
{
|
{
|
||||||
return !node->as<ASTFunction>() || (strcmp(inter_func_name, node->as<ASTFunction>()->name.c_str()) != 0);
|
switch (value.getType())
|
||||||
}
|
|
||||||
|
|
||||||
ASTFunction * getInternalFunction(const ASTFunction * f_n)
|
|
||||||
{
|
|
||||||
const auto * function_args = f_n->arguments->as<ASTExpressionList>();
|
|
||||||
if (!function_args || function_args->children.size() != 1)
|
|
||||||
throw Exception("Wrong number of arguments for function " + f_n->name + "(" + toString(function_args->children.size()) + " instead of 1)",
|
|
||||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
||||||
|
|
||||||
return f_n->arguments->children[0]->as<ASTFunction>();
|
|
||||||
}
|
|
||||||
|
|
||||||
ASTFunction * treeFiller(ASTFunction * old_tree, const ASTs & nodes_array, size_t size, const char * name, bool flag)
|
|
||||||
{
|
|
||||||
if (flag)
|
|
||||||
--size;
|
|
||||||
for (size_t i = 0; i < size; ++i)
|
|
||||||
{
|
{
|
||||||
old_tree->arguments->children = {};
|
case Field::Types::UInt64: return UInt64(0);
|
||||||
old_tree->arguments->children.push_back(nodes_array[i]);
|
case Field::Types::Int64: return Int64(0);
|
||||||
|
case Field::Types::Float64: return Float64(0);
|
||||||
old_tree->arguments->children.push_back(makeASTFunction(name));
|
case Field::Types::UInt128: return UInt128(0);
|
||||||
old_tree = old_tree->arguments->children[1]->as<ASTFunction>();
|
case Field::Types::Int128: return Int128(0);
|
||||||
}
|
default:
|
||||||
return old_tree;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
/// scalar values from the first level
|
|
||||||
std::pair<ASTs, ASTs> tryGetConst(const char * name, const ASTs & arguments)
|
|
||||||
{
|
|
||||||
ASTs const_num;
|
|
||||||
ASTs not_const;
|
|
||||||
|
|
||||||
for (const auto & arg : arguments)
|
|
||||||
{
|
|
||||||
if (const auto * literal = arg->as<ASTLiteral>())
|
|
||||||
{
|
|
||||||
if (isConstantField(literal->value))
|
|
||||||
const_num.push_back(arg);
|
|
||||||
else
|
|
||||||
not_const.push_back(arg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
not_const.push_back(arg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((strcmp(name, plus) == 0 || strcmp(name, mul) == 0) && const_num.size() + not_const.size() != 2)
|
throw Exception("Unexpected literal type in function", ErrorCodes::BAD_TYPE_OF_FIELD);
|
||||||
throw Exception("Wrong number of arguments for function 'plus' or 'multiply' (" + toString(const_num.size() + not_const.size()) + " instead of 2)",
|
|
||||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
||||||
|
|
||||||
return {const_num, not_const};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ASTs, ASTs> findAllConsts(const ASTFunction * func_node, const char * inter_func_name)
|
const String & changeNameIfNeeded(const String & func_name, const String & child_name, const ASTLiteral & literal)
|
||||||
{
|
{
|
||||||
if (func_node->arguments->children.empty())
|
static const std::unordered_map<String, std::unordered_set<String>> matches = {
|
||||||
|
{ "min", { "multiply", "divide" } },
|
||||||
|
{ "max", { "multiply", "divide" } }
|
||||||
|
};
|
||||||
|
|
||||||
|
static const std::unordered_map<String, String> swap_to = {
|
||||||
|
{ "min", "max" },
|
||||||
|
{ "max", "min" }
|
||||||
|
};
|
||||||
|
|
||||||
|
if (literal.value < zeroField(literal.value) && matches.count(func_name) && matches.find(func_name)->second.count(child_name))
|
||||||
|
return swap_to.find(func_name)->second;
|
||||||
|
|
||||||
|
return func_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTPtr tryExchangeFunctions(const ASTFunction & func)
|
||||||
|
{
|
||||||
|
static const std::unordered_map<String, std::unordered_set<String>> supported = {
|
||||||
|
{ "sum", { "multiply", "divide" } },
|
||||||
|
{ "min", { "multiply", "divide", "plus", "minus" } },
|
||||||
|
{ "max", { "multiply", "divide", "plus", "minus" } }
|
||||||
|
};
|
||||||
|
|
||||||
|
const ASTFunction * child_func = getInternalFunction(func);
|
||||||
|
if (!child_func || !child_func->arguments || child_func->arguments->children.size() != 2 ||
|
||||||
|
!supported.count(func.name) || !supported.find(func.name)->second.count(child_func->name))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
/// Cannot rewrite function with alias cause alias could become undefined
|
||||||
|
if (!func.tryGetAlias().empty() || !child_func->tryGetAlias().empty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const auto & child_func_args = child_func->arguments->children;
|
||||||
|
const auto * first_literal = child_func_args[0]->as<ASTLiteral>();
|
||||||
|
const auto * second_literal = child_func_args[1]->as<ASTLiteral>();
|
||||||
|
|
||||||
|
ASTPtr optimized_ast;
|
||||||
|
|
||||||
|
if (first_literal && !second_literal)
|
||||||
{
|
{
|
||||||
if (strcmp(func_node->name.c_str(), plus) == 0 || strcmp(func_node->name.c_str(), mul) == 0)
|
/// It's possible to rewrite 'sum(1/n)' with 'sum(1) * div(1/n)' but we lose accuracy. Ignored.
|
||||||
throw Exception("Wrong number of arguments for function" + func_node->name + "(0 instead of 2)",
|
if (child_func->name == "divide")
|
||||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
||||||
else
|
|
||||||
return {};
|
return {};
|
||||||
}
|
|
||||||
|
|
||||||
if (onlyConstsInside(func_node))
|
const String & new_name = changeNameIfNeeded(func.name, child_func->name, *first_literal);
|
||||||
return tryGetConst(func_node->name.c_str(), func_node->arguments->children);
|
optimized_ast = exchangeExtractFirstArgument(new_name, *child_func);
|
||||||
else if (inappropriateNameInside(func_node, inter_func_name))
|
}
|
||||||
|
else if (second_literal) /// second or both are consts
|
||||||
{
|
{
|
||||||
bool first_child_is_const = func_node->arguments->children[0]->as<ASTLiteral>() &&
|
const String & new_name = changeNameIfNeeded(func.name, child_func->name, *second_literal);
|
||||||
isConstantField(func_node->arguments->children[0]->as<ASTLiteral>()->value);
|
optimized_ast = exchangeExtractSecondArgument(new_name, *child_func);
|
||||||
bool second_child_is_const = func_node->arguments->children.size() == 2 &&
|
|
||||||
func_node->arguments->children[1]->as<ASTLiteral>() &&
|
|
||||||
isConstantField(func_node->arguments->children[1]->as<ASTLiteral>()->value);
|
|
||||||
if (first_child_is_const)
|
|
||||||
return {{func_node->arguments->children[0]}, {func_node->arguments->children[1]}};
|
|
||||||
else if (second_child_is_const)
|
|
||||||
return {{func_node->arguments->children[1]}, {func_node->arguments->children[0]}};
|
|
||||||
|
|
||||||
if (isInappropriate(func_node->arguments->children[0], inter_func_name)
|
|
||||||
&& isInappropriate(func_node->arguments->children[1], inter_func_name))
|
|
||||||
{
|
|
||||||
return {{}, {func_node->arguments->children[0], func_node->arguments->children[1]}};
|
|
||||||
}
|
|
||||||
else if (isInappropriate(func_node->arguments->children[0], inter_func_name))
|
|
||||||
{
|
|
||||||
std::pair<ASTs, ASTs> ans = findAllConsts(func_node->arguments->children[1]->as<ASTFunction>(), inter_func_name);
|
|
||||||
ans.second.push_back(func_node->arguments->children[0]);
|
|
||||||
return ans;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::pair<ASTs, ASTs> ans = findAllConsts(func_node->arguments->children[0]->as<ASTFunction>(), inter_func_name);
|
|
||||||
ans.second.push_back(func_node->arguments->children[1]);
|
|
||||||
return ans;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<ASTs, ASTs> fl = tryGetConst(func_node->name.c_str(), func_node->arguments->children);
|
return optimized_ast;
|
||||||
ASTs first_lvl_consts = fl.first;
|
|
||||||
ASTs first_lvl_not_consts = fl.second;
|
|
||||||
if (first_lvl_not_consts.empty() || !first_lvl_not_consts[0]->as<ASTFunction>())
|
|
||||||
return {first_lvl_consts, first_lvl_not_consts};
|
|
||||||
|
|
||||||
std::pair<ASTs, ASTs> ans = findAllConsts(first_lvl_not_consts[0]->as<ASTFunction>(), inter_func_name);
|
|
||||||
ASTs all_consts = ans.first;
|
|
||||||
ASTs all_not_consts = ans.second;
|
|
||||||
|
|
||||||
if (first_lvl_consts.size() == 1)
|
|
||||||
{
|
|
||||||
if (!first_lvl_not_consts[0]->as<ASTFunction>())
|
|
||||||
all_not_consts.push_back(first_lvl_not_consts[0]);
|
|
||||||
|
|
||||||
all_consts.push_back(first_lvl_consts[0]);
|
|
||||||
}
|
|
||||||
else if (first_lvl_consts.empty())
|
|
||||||
{
|
|
||||||
/// if node is inappropriate to go into it, we just add this node to all_not_consts vector
|
|
||||||
bool first_node_inappropriate_to_go_into = isInappropriate(first_lvl_not_consts[0], inter_func_name);
|
|
||||||
bool second_node_inappropriate_to_go_into = first_lvl_not_consts.size() == 2 &&
|
|
||||||
isInappropriate(first_lvl_not_consts[1], inter_func_name);
|
|
||||||
if (first_node_inappropriate_to_go_into)
|
|
||||||
all_not_consts.push_back(first_lvl_not_consts[0]);
|
|
||||||
|
|
||||||
if (second_node_inappropriate_to_go_into)
|
|
||||||
all_not_consts.push_back(first_lvl_not_consts[1]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw Exception("did not expect that", ErrorCodes::UNEXPECTED_AST_STRUCTURE);
|
|
||||||
return {all_consts, all_not_consts};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// rebuilds tree, all scalar values now outside the main func
|
}
|
||||||
void buildTree(ASTFunction * cur_node, const char * func_name, const char * intro_func, const std::pair<ASTs, ASTs> & tree_comp)
|
|
||||||
|
|
||||||
|
void ArithmeticOperationsInAgrFuncMatcher::visit(const ASTFunction & func, ASTPtr & ast, Data & data)
|
||||||
{
|
{
|
||||||
ASTs cons_val = tree_comp.first;
|
if (auto exchanged_funcs = tryExchangeFunctions(func))
|
||||||
ASTs non_cons = tree_comp.second;
|
|
||||||
|
|
||||||
bool not_const_empty = non_cons.empty();
|
|
||||||
|
|
||||||
cur_node->name = intro_func;
|
|
||||||
cur_node = treeFiller(cur_node, cons_val, cons_val.size(), intro_func, not_const_empty);
|
|
||||||
cur_node->name = func_name;
|
|
||||||
|
|
||||||
if (non_cons.empty())
|
|
||||||
cur_node->arguments->children.push_back(cons_val[cons_val.size() - 1]);
|
|
||||||
else if (non_cons.size() == 1)
|
|
||||||
cur_node->arguments->children.push_back(non_cons[0]);
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
cur_node->arguments->children.push_back(makeASTFunction(intro_func));
|
ast = exchanged_funcs;
|
||||||
cur_node = cur_node->arguments->children[0]->as<ASTFunction>();
|
|
||||||
cur_node = treeFiller(cur_node, non_cons, non_cons.size() - 2, intro_func, not_const_empty);
|
/// Main visitor is bottom-up. This is top-down part.
|
||||||
cur_node->arguments->children = {non_cons[non_cons.size() - 2], non_cons[non_cons.size() - 1]};
|
/// We've found an aggregate function an now move it down through others: sum(mul(mul)) -> mul(mul(sum)).
|
||||||
|
/// It's not dangerous cause main visitor already has visited this part of tree.
|
||||||
|
auto & expression_list = ast->children[0];
|
||||||
|
visit(expression_list->children[0], data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sumOptimize(ASTFunction * f_n)
|
void ArithmeticOperationsInAgrFuncMatcher::visit(ASTPtr & ast, Data & data)
|
||||||
{
|
{
|
||||||
const auto * function_args = f_n->arguments->as<ASTExpressionList>();
|
if (const auto * function_node = ast->as<ASTFunction>())
|
||||||
|
visit(*function_node, ast, data);
|
||||||
if (!function_args || function_args->children.size() != 1)
|
|
||||||
throw Exception("Wrong number of arguments for function 'sum' (" + toString(function_args->children.size()) + " instead of 1)",
|
|
||||||
ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH);
|
|
||||||
|
|
||||||
ASTFunction * inter_node = getInternalFunction(f_n);
|
|
||||||
if (inter_node && inter_node->name == mul)
|
|
||||||
{
|
|
||||||
std::pair<ASTs, ASTs> nodes = findAllConsts(f_n, mul);
|
|
||||||
|
|
||||||
if (nodes.first.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
buildTree(f_n, sum, mul, nodes);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void minOptimize(ASTFunction * f_n)
|
bool ArithmeticOperationsInAgrFuncMatcher::needChildVisit(const ASTPtr & node, const ASTPtr &)
|
||||||
{
|
{
|
||||||
ASTFunction * inter_node = getInternalFunction(f_n);
|
return !node->as<ASTSubquery>() && !node->as<ASTTableExpression>();
|
||||||
if (inter_node && inter_node->name == mul)
|
|
||||||
{
|
|
||||||
int sign = 1;
|
|
||||||
std::pair<ASTs, ASTs> nodes = findAllConsts(f_n, mul);
|
|
||||||
|
|
||||||
if (nodes.first.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const auto & arg : nodes.first)
|
|
||||||
{
|
|
||||||
Int128 num = applyVisitor(FieldVisitorConvertToNumber<Int128>(), arg->as<ASTLiteral>()->value);
|
|
||||||
|
|
||||||
/// if multiplication is negative, min function becomes max
|
|
||||||
|
|
||||||
if ((arg->as<ASTLiteral>()->value.getType() == Field::Types::Int64 ||
|
|
||||||
arg->as<ASTLiteral>()->value.getType() == Field::Types::Int128) && num < static_cast<Int128>(0))
|
|
||||||
sign *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sign == -1)
|
|
||||||
buildTree(f_n, max, mul, nodes);
|
|
||||||
else
|
|
||||||
buildTree(f_n, min, mul, nodes);
|
|
||||||
}
|
|
||||||
else if (inter_node && inter_node->name == plus)
|
|
||||||
{
|
|
||||||
std::pair<ASTs, ASTs> nodes = findAllConsts(f_n, plus);
|
|
||||||
buildTree(f_n, min, plus, nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void maxOptimize(ASTFunction * f_n)
|
|
||||||
{
|
|
||||||
ASTFunction * inter_node = getInternalFunction(f_n);
|
|
||||||
if (inter_node && inter_node->name == mul)
|
|
||||||
{
|
|
||||||
int sign = 1;
|
|
||||||
std::pair<ASTs, ASTs> nodes = findAllConsts(f_n, mul);
|
|
||||||
|
|
||||||
if (nodes.first.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (const auto & arg: nodes.first)
|
|
||||||
{
|
|
||||||
Int128 num = applyVisitor(FieldVisitorConvertToNumber<Int128>(), arg->as<ASTLiteral>()->value);
|
|
||||||
|
|
||||||
/// if multiplication is negative, max function becomes min
|
|
||||||
if ((arg->as<ASTLiteral>()->value.getType() == Field::Types::Int64 ||
|
|
||||||
arg->as<ASTLiteral>()->value.getType() == Field::Types::Int128) && num < static_cast<Int128>(0))
|
|
||||||
sign *= -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sign == -1)
|
|
||||||
buildTree(f_n, min, mul, nodes);
|
|
||||||
else
|
|
||||||
buildTree(f_n, max, mul, nodes);
|
|
||||||
}
|
|
||||||
else if (inter_node && inter_node->name == plus)
|
|
||||||
{
|
|
||||||
std::pair<ASTs, ASTs> nodes = findAllConsts(f_n, plus);
|
|
||||||
buildTree(f_n, max, plus, nodes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// optimize for min, max, sum is ready, ToDo: groupBitAnd, groupBitOr, groupBitXor
|
|
||||||
void ArithmeticOperationsInAgrFuncMatcher::visit(ASTFunction * function_node, Data data)
|
|
||||||
{
|
|
||||||
data = {};
|
|
||||||
if (function_node->name == sum)
|
|
||||||
sumOptimize(function_node);
|
|
||||||
else if (function_node->name == min)
|
|
||||||
minOptimize(function_node);
|
|
||||||
else if (function_node->name == max)
|
|
||||||
maxOptimize(function_node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ArithmeticOperationsInAgrFuncMatcher::visit(const ASTPtr & current_ast, Data data)
|
|
||||||
{
|
|
||||||
if (!current_ast)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (auto * function_node = current_ast->as<ASTFunction>())
|
|
||||||
visit(function_node, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ArithmeticOperationsInAgrFuncMatcher::needChildVisit(const ASTPtr & node, const ASTPtr & child)
|
|
||||||
{
|
|
||||||
if (!child)
|
|
||||||
throw Exception("AST item should not have nullptr in children", ErrorCodes::LOGICAL_ERROR);
|
|
||||||
|
|
||||||
return !(node->as<ASTTableExpression>() || node->as<ASTArrayJoin>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,17 +6,24 @@
|
|||||||
namespace DB
|
namespace DB
|
||||||
{
|
{
|
||||||
|
|
||||||
/// It converts some arithmetic. Optimization due to the linearity property of some aggregate functions.
|
/// Extract constant arguments out of aggregate functions from child functions
|
||||||
/// Function collects const and not const nodes and rebuilds old tree.
|
/// 'sum(a * 2)' -> 'sum(a) * 2'
|
||||||
|
/// Rewrites: sum([multiply|divide]) -> [multiply|divide](sum)
|
||||||
|
/// [min|max]([multiply|divide|plus|minus]) -> [multiply|divide|plus|minus]([min|max])
|
||||||
|
/// TODO: groupBitAnd, groupBitOr, groupBitXor
|
||||||
|
/// TODO: better constant detection: f(const) is not detected as const.
|
||||||
|
/// TODO: 'f((2 * n) * n)' -> '2 * f(n * n)'
|
||||||
class ArithmeticOperationsInAgrFuncMatcher
|
class ArithmeticOperationsInAgrFuncMatcher
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Data {};
|
struct Data {};
|
||||||
|
|
||||||
static void visit(const ASTPtr & ast, Data data);
|
static void visit(ASTPtr & ast, Data & data);
|
||||||
static void visit(ASTFunction *, Data data);
|
static void visit(const ASTFunction &, ASTPtr & ast, Data & data);
|
||||||
static bool needChildVisit(const ASTPtr & node, const ASTPtr & child);
|
|
||||||
|
|
||||||
|
static bool needChildVisit(const ASTPtr & node, const ASTPtr & child);
|
||||||
};
|
};
|
||||||
using ArithmeticOperationsInAgrFuncVisitor = InDepthNodeVisitor<ArithmeticOperationsInAgrFuncMatcher, true>;
|
|
||||||
|
using ArithmeticOperationsInAgrFuncVisitor = InDepthNodeVisitor<ArithmeticOperationsInAgrFuncMatcher, false>;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -555,14 +555,11 @@ void optimizeIf(ASTPtr & query, Aliases & aliases, bool if_chain_to_miltiif)
|
|||||||
OptimizeIfChainsVisitor().visit(query);
|
OptimizeIfChainsVisitor().visit(query);
|
||||||
}
|
}
|
||||||
|
|
||||||
void optimizeArithmeticOperationsInAgr(ASTPtr & query, bool optimize_arithmetic_operations_in_agr_func)
|
void optimizeAggregationFunctions(ASTPtr & query)
|
||||||
{
|
{
|
||||||
if (optimize_arithmetic_operations_in_agr_func)
|
/// Move arithmetic operations out of aggregation functions
|
||||||
{
|
ArithmeticOperationsInAgrFuncVisitor::Data data;
|
||||||
/// Removing arithmetic operations from functions
|
ArithmeticOperationsInAgrFuncVisitor(data).visit(query);
|
||||||
ArithmeticOperationsInAgrFuncVisitor::Data data = {};
|
|
||||||
ArithmeticOperationsInAgrFuncVisitor(data).visit(query);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void optimizeAnyInput(ASTPtr & query)
|
void optimizeAnyInput(ASTPtr & query)
|
||||||
@ -952,7 +949,8 @@ SyntaxAnalyzerResultPtr SyntaxAnalyzer::analyzeSelect(
|
|||||||
optimizeIf(query, result.aliases, settings.optimize_if_chain_to_miltiif);
|
optimizeIf(query, result.aliases, settings.optimize_if_chain_to_miltiif);
|
||||||
|
|
||||||
/// Move arithmetic operations out of aggregation functions
|
/// Move arithmetic operations out of aggregation functions
|
||||||
optimizeArithmeticOperationsInAgr(query, settings.optimize_arithmetic_operations_in_aggregate_functions);
|
if (settings.optimize_arithmetic_operations_in_aggregate_functions)
|
||||||
|
optimizeAggregationFunctions(query);
|
||||||
|
|
||||||
/// Push the predicate expression down to the subqueries.
|
/// Push the predicate expression down to the subqueries.
|
||||||
result.rewrite_subqueries = PredicateExpressionsOptimizer(context, tables_with_columns, settings).optimize(*select_query);
|
result.rewrite_subqueries = PredicateExpressionsOptimizer(context, tables_with_columns, settings).optimize(*select_query);
|
||||||
|
@ -1,6 +1,150 @@
|
|||||||
|
SELECT \n sum(n + 1),\n sum(1 + n),\n sum(n - 1),\n sum(1 - n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(n) * 2,\n 2 * sum(n),\n sum(n) / 2,\n sum(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(n) + 1,\n 1 + min(n),\n min(n) - 1,\n 1 - min(n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(n) * 2,\n 2 * min(n),\n min(n) / 2,\n min(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(n) + 1,\n 1 + max(n),\n max(n) - 1,\n 1 - max(n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(n) * 2,\n 2 * max(n),\n max(n) / 2,\n max(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(n + -1),\n sum(-1 + n),\n sum(n - -1),\n sum(-1 - n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(n) * -2,\n -2 * sum(n),\n sum(n) / -2,\n sum(-1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(n) + -1,\n -1 + min(n),\n min(n) - -1,\n -1 - min(n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(n) * -2,\n -2 * max(n),\n max(n) / -2,\n min(-1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(n) + -1,\n -1 + max(n),\n max(n) - -1,\n -1 - max(n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(n) * -2,\n -2 * min(n),\n min(n) / -2,\n max(-1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(abs(2) + 1),\n sum(abs(2) + n),\n sum(n - abs(2)),\n sum(1 - abs(2))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(abs(2)) * 2,\n sum(abs(2) * n),\n sum(n / abs(2)),\n sum(1 / abs(2))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(abs(2)) + 1,\n min(abs(2) + n),\n min(n - abs(2)),\n 1 - min(abs(2))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(abs(2)) * 2,\n min(abs(2) * n),\n min(n / abs(2)),\n min(1 / abs(2))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(abs(2)) + 1,\n max(abs(2) + n),\n max(n - abs(2)),\n 1 - max(abs(2))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(abs(2)) * 2,\n max(abs(2) * n),\n max(n / abs(2)),\n max(1 / abs(2))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(abs(n) + 1),\n sum(abs(n) + n),\n sum(n - abs(n)),\n sum(1 - abs(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(abs(n)) * 2,\n sum(abs(n) * n),\n sum(n / abs(n)),\n sum(1 / abs(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(abs(n)) + 1,\n min(abs(n) + n),\n min(n - abs(n)),\n 1 - min(abs(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(abs(n)) * 2,\n min(abs(n) * n),\n min(n / abs(n)),\n min(1 / abs(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(abs(n)) + 1,\n max(abs(n) + n),\n max(n - abs(n)),\n 1 - max(abs(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(abs(n)) * 2,\n max(abs(n) * n),\n max(n / abs(n)),\n max(1 / abs(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum((n * n) + 1),\n sum(1 + (n * n)),\n sum((n * n) - 1),\n sum(1 - (n * n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(n * n) * 2,\n sum((2 * n) * n),\n sum(n * n) / 2,\n sum((1 / n) * n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(n * n) + 1,\n 1 + min(n * n),\n min(n * n) - 1,\n 1 - min(n * n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n min(n * n) * 2,\n min((2 * n) * n),\n min(n * n) / 2,\n min((1 / n) * n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(n * n) + 1,\n 1 + max(n * n),\n max(n * n) - 1,\n 1 - max(n * n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n max(n * n) * 2,\n max((2 * n) * n),\n max(n * n) / 2,\n max((1 / n) * n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum((1 + n) + 1),\n sum((1 + 1) + n),\n sum((1 + n) - 1),\n sum((1 + 1) - n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum(1 + (n * 2)),\n sum(1 + (2 * n)),\n sum(1 + (n / 2)),\n sum(1 + (1 / n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (1 + min(n)) + 1,\n min((1 + 1) + n),\n (1 + min(n)) - 1,\n min((1 + 1) - n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n 1 + min(n * 2),\n 1 + min(2 * n),\n 1 + min(n / 2),\n 1 + min(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (1 + max(n)) + 1,\n max((1 + 1) + n),\n (1 + max(n)) - 1,\n max((1 + 1) - n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n 1 + max(n * 2),\n 1 + max(2 * n),\n 1 + max(n / 2),\n 1 + max(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n sum((n + -1) + -1),\n sum((-1 + n) + -1),\n sum((n - -1) + -1),\n sum((-1 - n) + -1)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (sum(n) * -2) * -1,\n (-2 * sum(n)) * -1,\n (sum(n) / -2) / -1,\n sum(-1 / n) / -1\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (min(n) + -1) + -1,\n (-1 + min(n)) + -1,\n (min(n) - -1) + -1,\n (-1 - min(n)) + -1\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (min(n) * -2) * -1,\n (-2 * min(n)) * -1,\n (min(n) / -2) / -1,\n max(-1 / n) / -1\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (max(n) + -1) + -1,\n (-1 + max(n)) + -1,\n (max(n) - -1) + -1,\n (-1 - max(n)) + -1\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT \n (max(n) * -2) * -1,\n (-2 * max(n)) * -1,\n (max(n) / -2) / -1,\n min(-1 / n) / -1\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT ((sum(n + 1) + sum(1 + n)) + sum(n - 1)) + sum(1 - n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT (((sum(n) * 2) + (2 * sum(n))) + (sum(n) / 2)) + sum(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT (((min(n) + 1) + (1 + min(n))) + (min(n) - 1)) + (1 - min(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT (((min(n) * 2) + (2 * min(n))) + (min(n) / 2)) + min(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT (((max(n) + 1) + (1 + max(n))) + (max(n) - 1)) + (1 - max(n))\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
SELECT (((max(n) * 2) + (2 * max(n))) + (max(n) / 2)) + max(1 / n)\nFROM \n(\n SELECT number AS n\n FROM numbers(10)\n)
|
||||||
|
55 55 35 -35
|
||||||
|
90 90 22.5 inf
|
||||||
|
1 1 -1 1
|
||||||
|
0 0 0 0.1111111111111111
|
||||||
|
10 10 8 -8
|
||||||
|
18 18 4.5 inf
|
||||||
|
35 35 55 -55
|
||||||
|
-90 -90 -22.5 -inf
|
||||||
|
-1 -1 1 -1
|
||||||
|
-18 -18 -4.5 -inf
|
||||||
|
8 8 10 -10
|
||||||
|
0 0 -0 -0.1111111111111111
|
||||||
|
30 65 25 -10
|
||||||
|
40 90 22.5 5
|
||||||
|
3 2 -2 -1
|
||||||
|
4 0 0 0.5
|
||||||
|
3 11 7 -1
|
||||||
|
4 18 4.5 0.5
|
||||||
|
55 90 0 -35
|
||||||
|
90 285 nan inf
|
||||||
|
1 0 0 1
|
||||||
|
0 0 nan 0.1111111111111111
|
||||||
|
10 18 0 -8
|
||||||
|
18 81 nan inf
|
||||||
|
295 295 275 -275
|
||||||
|
570 570 142.5 nan
|
||||||
|
1 1 -1 1
|
||||||
|
0 0 0 nan
|
||||||
|
82 82 80 -80
|
||||||
|
162 162 40.5 nan
|
||||||
|
65 65 45 -25
|
||||||
|
100 100 32.5 inf
|
||||||
|
2 2 0 -7
|
||||||
|
1 1 1 1.1111111111111112
|
||||||
|
11 11 9 2
|
||||||
|
19 19 5.5 inf
|
||||||
|
25 25 45 -65
|
||||||
|
90 90 22.5 inf
|
||||||
|
-2 -2 0 -2
|
||||||
|
0 0 0 0.1111111111111111
|
||||||
|
7 7 9 -11
|
||||||
|
18 18 4.5 inf
|
||||||
|
110
|
||||||
|
inf
|
||||||
|
2
|
||||||
|
0.1111111111111111
|
||||||
|
20
|
||||||
|
inf
|
||||||
-15444
|
-15444
|
||||||
68.62157087543459
|
68.62157087543459
|
||||||
243
|
243
|
||||||
|
55 55 35 -35
|
||||||
|
90 90 22.5 inf
|
||||||
|
1 1 -1 -8
|
||||||
|
0 0 0 0.1111111111111111
|
||||||
|
10 10 8 1
|
||||||
|
18 18 4.5 inf
|
||||||
|
35 35 55 -55
|
||||||
|
-90 -90 -22.5 -inf
|
||||||
|
-1 -1 1 -10
|
||||||
|
-18 -18 -4.5 -inf
|
||||||
|
8 8 10 -1
|
||||||
|
0 0 -0 -0.1111111111111111
|
||||||
|
30 65 25 -10
|
||||||
|
40 90 22.5 5
|
||||||
|
3 2 -2 -1
|
||||||
|
4 0 0 0.5
|
||||||
|
3 11 7 -1
|
||||||
|
4 18 4.5 0.5
|
||||||
|
55 90 0 -35
|
||||||
|
90 285 nan inf
|
||||||
|
1 0 0 -8
|
||||||
|
0 0 nan 0.1111111111111111
|
||||||
|
10 18 0 1
|
||||||
|
18 81 nan inf
|
||||||
|
295 295 275 -275
|
||||||
|
570 570 142.5 nan
|
||||||
|
1 1 -1 -80
|
||||||
|
0 0 0 nan
|
||||||
|
82 82 80 1
|
||||||
|
162 162 40.5 nan
|
||||||
|
65 65 45 -25
|
||||||
|
100 100 32.5 inf
|
||||||
|
2 2 0 -7
|
||||||
|
1 1 1 1.1111111111111112
|
||||||
|
11 11 9 2
|
||||||
|
19 19 5.5 inf
|
||||||
|
25 25 45 -65
|
||||||
|
90 90 22.5 inf
|
||||||
|
-2 -2 0 -11
|
||||||
|
0 0 0 0.1111111111111111
|
||||||
|
7 7 9 -2
|
||||||
|
18 18 4.5 inf
|
||||||
|
110
|
||||||
|
inf
|
||||||
|
-7
|
||||||
|
0.1111111111111111
|
||||||
|
29
|
||||||
|
inf
|
||||||
-15444
|
-15444
|
||||||
68.62157087543459
|
68.62157087543459
|
||||||
243
|
243
|
||||||
|
@ -1,10 +1,182 @@
|
|||||||
set optimize_arithmetic_operations_in_aggregate_functions = 1;
|
SET enable_debug_queries = 1;
|
||||||
|
SET optimize_arithmetic_operations_in_aggregate_functions = 1;
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(n + 1), sum(1 + n), sum(n - 1), sum(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(n * 2), sum(2 * n), sum(n / 2), sum(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n + 1), min(1 + n), min(n - 1), min(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n * 2), min(2 * n), min(n / 2), min(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n + 1), max(1 + n), max(n - 1), max(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n * 2), max(2 * n), max(n / 2), max(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(n + -1), sum(-1 + n), sum(n - -1), sum(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(n * -2), sum(-2 * n), sum(n / -2), sum(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n + -1), min(-1 + n), min(n - -1), min(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n * -2), min(-2 * n), min(n / -2), min(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n + -1), max(-1 + n), max(n - -1), max(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n * -2), max(-2 * n), max(n / -2), max(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(abs(2) + 1), sum(abs(2) + n), sum(n - abs(2)), sum(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(abs(2) * 2), sum(abs(2) * n), sum(n / abs(2)), sum(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(abs(2) + 1), min(abs(2) + n), min(n - abs(2)), min(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(abs(2) * 2), min(abs(2) * n), min(n / abs(2)), min(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(abs(2) + 1), max(abs(2) + n), max(n - abs(2)), max(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(abs(2) * 2), max(abs(2) * n), max(n / abs(2)), max(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(abs(n) + 1), sum(abs(n) + n), sum(n - abs(n)), sum(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(abs(n) * 2), sum(abs(n) * n), sum(n / abs(n)), sum(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(abs(n) + 1), min(abs(n) + n), min(n - abs(n)), min(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(abs(n) * 2), min(abs(n) * n), min(n / abs(n)), min(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(abs(n) + 1), max(abs(n) + n), max(n - abs(n)), max(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(abs(n) * 2), max(abs(n) * n), max(n / abs(n)), max(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(n*n + 1), sum(1 + n*n), sum(n*n - 1), sum(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(n*n * 2), sum(2 * n*n), sum(n*n / 2), sum(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n*n + 1), min(1 + n*n), min(n*n - 1), min(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n*n * 2), min(2 * n*n), min(n*n / 2), min(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n*n + 1), max(1 + n*n), max(n*n - 1), max(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n*n * 2), max(2 * n*n), max(n*n / 2), max(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(1 + n + 1), sum(1 + 1 + n), sum(1 + n - 1), sum(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(1 + n * 2), sum(1 + 2 * n), sum(1 + n / 2), sum(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(1 + n + 1), min(1 + 1 + n), min(1 + n - 1), min(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(1 + n * 2), min(1 + 2 * n), min(1 + n / 2), min(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(1 + n + 1), max(1 + 1 + n), max(1 + n - 1), max(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(1 + n * 2), max(1 + 2 * n), max(1 + n / 2), max(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(n + -1 + -1), sum(-1 + n + -1), sum(n - -1 + -1), sum(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(n * -2 * -1), sum(-2 * n * -1), sum(n / -2 / -1), sum(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n + -1 + -1), min(-1 + n + -1), min(n - -1 + -1), min(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n * -2 * -1), min(-2 * n * -1), min(n / -2 / -1), min(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n + -1 + -1), max(-1 + n + -1), max(n - -1 + -1), max(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n * -2 * -1), max(-2 * n * -1), max(n / -2 / -1), max(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
ANALYZE SELECT sum(n + 1) + sum(1 + n) + sum(n - 1) + sum(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT sum(n * 2) + sum(2 * n) + sum(n / 2) + sum(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n + 1) + min(1 + n) + min(n - 1) + min(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT min(n * 2) + min(2 * n) + min(n / 2) + min(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n + 1) + max(1 + n) + max(n - 1) + max(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
ANALYZE SELECT max(n * 2) + max(2 * n) + max(n / 2) + max(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
|
||||||
|
SELECT sum(n + 1), sum(1 + n), sum(n - 1), sum(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * 2), sum(2 * n), sum(n / 2), sum(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + 1), min(1 + n), min(n - 1), min(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * 2), min(2 * n), min(n / 2), min(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + 1), max(1 + n), max(n - 1), max(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * 2), max(2 * n), max(n / 2), max(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n + -1), sum(-1 + n), sum(n - -1), sum(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * -2), sum(-2 * n), sum(n / -2), sum(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + -1), min(-1 + n), min(n - -1), min(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * -2), min(-2 * n), min(n / -2), min(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + -1), max(-1 + n), max(n - -1), max(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * -2), max(-2 * n), max(n / -2), max(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(abs(2) + 1), sum(abs(2) + n), sum(n - abs(2)), sum(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(abs(2) * 2), sum(abs(2) * n), sum(n / abs(2)), sum(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(2) + 1), min(abs(2) + n), min(n - abs(2)), min(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(2) * 2), min(abs(2) * n), min(n / abs(2)), min(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(2) + 1), max(abs(2) + n), max(n - abs(2)), max(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(2) * 2), max(abs(2) * n), max(n / abs(2)), max(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(abs(n) + 1), sum(abs(n) + n), sum(n - abs(n)), sum(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(abs(n) * 2), sum(abs(n) * n), sum(n / abs(n)), sum(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(n) + 1), min(abs(n) + n), min(n - abs(n)), min(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(n) * 2), min(abs(n) * n), min(n / abs(n)), min(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(n) + 1), max(abs(n) + n), max(n - abs(n)), max(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(n) * 2), max(abs(n) * n), max(n / abs(n)), max(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n*n + 1), sum(1 + n*n), sum(n*n - 1), sum(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n*n * 2), sum(2 * n*n), sum(n*n / 2), sum(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n*n + 1), min(1 + n*n), min(n*n - 1), min(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n*n * 2), min(2 * n*n), min(n*n / 2), min(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n*n + 1), max(1 + n*n), max(n*n - 1), max(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n*n * 2), max(2 * n*n), max(n*n / 2), max(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(1 + n + 1), sum(1 + 1 + n), sum(1 + n - 1), sum(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(1 + n * 2), sum(1 + 2 * n), sum(1 + n / 2), sum(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(1 + n + 1), min(1 + 1 + n), min(1 + n - 1), min(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(1 + n * 2), min(1 + 2 * n), min(1 + n / 2), min(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(1 + n + 1), max(1 + 1 + n), max(1 + n - 1), max(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(1 + n * 2), max(1 + 2 * n), max(1 + n / 2), max(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n + -1 + -1), sum(-1 + n + -1), sum(n - -1 + -1), sum(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * -2 * -1), sum(-2 * n * -1), sum(n / -2 / -1), sum(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + -1 + -1), min(-1 + n + -1), min(n - -1 + -1), min(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * -2 * -1), min(-2 * n * -1), min(n / -2 / -1), min(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + -1 + -1), max(-1 + n + -1), max(n - -1 + -1), max(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * -2 * -1), max(-2 * n * -1), max(n / -2 / -1), max(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n + 1) + sum(1 + n) + sum(n - 1) + sum(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * 2) + sum(2 * n) + sum(n / 2) + sum(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + 1) + min(1 + n) + min(n - 1) + min(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * 2) + min(2 * n) + min(n / 2) + min(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + 1) + max(1 + n) + max(n - 1) + max(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * 2) + max(2 * n) + max(n / 2) + max(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
|
||||||
SELECT sum(number * -3) + min(2 * number * -3) - max(-1 * -2 * number * -3) FROM numbers(100);
|
SELECT sum(number * -3) + min(2 * number * -3) - max(-1 * -2 * number * -3) FROM numbers(100);
|
||||||
SELECT max(log(2) * number) FROM numbers(100);
|
SELECT max(log(2) * number) FROM numbers(100);
|
||||||
SELECT round(max(log(2) * 3 * sin(0.3) * number * 4)) FROM numbers(100);
|
SELECT round(max(log(2) * 3 * sin(0.3) * number * 4)) FROM numbers(100);
|
||||||
|
|
||||||
set optimize_arithmetic_operations_in_aggregate_functions = 0;
|
SET optimize_arithmetic_operations_in_aggregate_functions = 0;
|
||||||
|
|
||||||
|
SELECT sum(n + 1), sum(1 + n), sum(n - 1), sum(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * 2), sum(2 * n), sum(n / 2), sum(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + 1), min(1 + n), min(n - 1), min(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * 2), min(2 * n), min(n / 2), min(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + 1), max(1 + n), max(n - 1), max(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * 2), max(2 * n), max(n / 2), max(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n + -1), sum(-1 + n), sum(n - -1), sum(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * -2), sum(-2 * n), sum(n / -2), sum(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + -1), min(-1 + n), min(n - -1), min(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * -2), min(-2 * n), min(n / -2), min(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + -1), max(-1 + n), max(n - -1), max(-1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * -2), max(-2 * n), max(n / -2), max(-1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(abs(2) + 1), sum(abs(2) + n), sum(n - abs(2)), sum(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(abs(2) * 2), sum(abs(2) * n), sum(n / abs(2)), sum(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(2) + 1), min(abs(2) + n), min(n - abs(2)), min(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(2) * 2), min(abs(2) * n), min(n / abs(2)), min(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(2) + 1), max(abs(2) + n), max(n - abs(2)), max(1 - abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(2) * 2), max(abs(2) * n), max(n / abs(2)), max(1 / abs(2)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(abs(n) + 1), sum(abs(n) + n), sum(n - abs(n)), sum(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(abs(n) * 2), sum(abs(n) * n), sum(n / abs(n)), sum(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(n) + 1), min(abs(n) + n), min(n - abs(n)), min(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(abs(n) * 2), min(abs(n) * n), min(n / abs(n)), min(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(n) + 1), max(abs(n) + n), max(n - abs(n)), max(1 - abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(abs(n) * 2), max(abs(n) * n), max(n / abs(n)), max(1 / abs(n)) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n*n + 1), sum(1 + n*n), sum(n*n - 1), sum(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n*n * 2), sum(2 * n*n), sum(n*n / 2), sum(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n*n + 1), min(1 + n*n), min(n*n - 1), min(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n*n * 2), min(2 * n*n), min(n*n / 2), min(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n*n + 1), max(1 + n*n), max(n*n - 1), max(1 - n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n*n * 2), max(2 * n*n), max(n*n / 2), max(1 / n*n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(1 + n + 1), sum(1 + 1 + n), sum(1 + n - 1), sum(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(1 + n * 2), sum(1 + 2 * n), sum(1 + n / 2), sum(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(1 + n + 1), min(1 + 1 + n), min(1 + n - 1), min(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(1 + n * 2), min(1 + 2 * n), min(1 + n / 2), min(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(1 + n + 1), max(1 + 1 + n), max(1 + n - 1), max(1 + 1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(1 + n * 2), max(1 + 2 * n), max(1 + n / 2), max(1 + 1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n + -1 + -1), sum(-1 + n + -1), sum(n - -1 + -1), sum(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * -2 * -1), sum(-2 * n * -1), sum(n / -2 / -1), sum(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + -1 + -1), min(-1 + n + -1), min(n - -1 + -1), min(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * -2 * -1), min(-2 * n * -1), min(n / -2 / -1), min(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + -1 + -1), max(-1 + n + -1), max(n - -1 + -1), max(-1 - n + -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * -2 * -1), max(-2 * n * -1), max(n / -2 / -1), max(-1 / n / -1) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
SELECT sum(n + 1) + sum(1 + n) + sum(n - 1) + sum(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT sum(n * 2) + sum(2 * n) + sum(n / 2) + sum(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n + 1) + min(1 + n) + min(n - 1) + min(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT min(n * 2) + min(2 * n) + min(n / 2) + min(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n + 1) + max(1 + n) + max(n - 1) + max(1 - n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
SELECT max(n * 2) + max(2 * n) + max(n / 2) + max(1 / n) FROM (SELECT number n FROM numbers(10));
|
||||||
|
|
||||||
|
|
||||||
SELECT sum(number * -3) + min(2 * number * -3) - max(-1 * -2 * number * -3) FROM numbers(100);
|
SELECT sum(number * -3) + min(2 * number * -3) - max(-1 * -2 * number * -3) FROM numbers(100);
|
||||||
SELECT max(log(2) * number) FROM numbers(100);
|
SELECT max(log(2) * number) FROM numbers(100);
|
||||||
|
Loading…
Reference in New Issue
Block a user