mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 00:30:49 +00:00
Merge pull request #26657 from hexiaoting/fuse_quantile
This commit is contained in:
commit
bc7c41efff
@ -3343,7 +3343,7 @@ Result:
|
||||
└─────┘
|
||||
```
|
||||
|
||||
## optimize_fuse_sum_count_avg {#optimize_fuse_sum_count_avg}
|
||||
## optimize_syntax_fuse_functions {#optimize_syntax_fuse_functions}
|
||||
|
||||
Enables to fuse aggregate functions with identical argument. It rewrites query contains at least two aggregate functions from [sum](../../sql-reference/aggregate-functions/reference/sum.md#agg_function-sum), [count](../../sql-reference/aggregate-functions/reference/count.md#agg_function-count) or [avg](../../sql-reference/aggregate-functions/reference/avg.md#agg_function-avg) with identical argument to [sumCount](../../sql-reference/aggregate-functions/reference/sumcount.md#agg_function-sumCount).
|
||||
|
||||
@ -3360,7 +3360,7 @@ Query:
|
||||
|
||||
``` sql
|
||||
CREATE TABLE fuse_tbl(a Int8, b Int8) Engine = Log;
|
||||
SET optimize_fuse_sum_count_avg = 1;
|
||||
SET optimize_syntax_fuse_functions = 1;
|
||||
EXPLAIN SYNTAX SELECT sum(a), sum(b), count(b), avg(b) from fuse_tbl FORMAT TSV;
|
||||
```
|
||||
|
||||
|
@ -43,4 +43,4 @@ Result:
|
||||
|
||||
**See also**
|
||||
|
||||
- [optimize_fuse_sum_count_avg](../../../operations/settings/settings.md#optimize_fuse_sum_count_avg) setting.
|
||||
- [optimize_syntax_fuse_functions](../../../operations/settings/settings.md#optimize_syntax_fuse_functions) setting.
|
||||
|
@ -3122,7 +3122,7 @@ SELECT * FROM test LIMIT 10 OFFSET 100;
|
||||
|
||||
Значение по умолчанию: `1800`.
|
||||
|
||||
## optimize_fuse_sum_count_avg {#optimize_fuse_sum_count_avg}
|
||||
## optimize_syntax_fuse_functions {#optimize_syntax_fuse_functions}
|
||||
|
||||
Позволяет объединить агрегатные функции с одинаковым аргументом. Запрос, содержащий по крайней мере две агрегатные функции: [sum](../../sql-reference/aggregate-functions/reference/sum.md#agg_function-sum), [count](../../sql-reference/aggregate-functions/reference/count.md#agg_function-count) или [avg](../../sql-reference/aggregate-functions/reference/avg.md#agg_function-avg) с одинаковым аргументом, перезаписывается как [sumCount](../../sql-reference/aggregate-functions/reference/sumcount.md#agg_function-sumCount).
|
||||
|
||||
@ -3139,7 +3139,7 @@ SELECT * FROM test LIMIT 10 OFFSET 100;
|
||||
|
||||
``` sql
|
||||
CREATE TABLE fuse_tbl(a Int8, b Int8) Engine = Log;
|
||||
SET optimize_fuse_sum_count_avg = 1;
|
||||
SET optimize_syntax_fuse_functions = 1;
|
||||
EXPLAIN SYNTAX SELECT sum(a), sum(b), count(b), avg(b) from fuse_tbl FORMAT TSV;
|
||||
```
|
||||
|
||||
|
@ -43,4 +43,4 @@ SELECT sumCount(x) from s_table;
|
||||
|
||||
**Смотрите также**
|
||||
|
||||
- Настройка [optimize_fuse_sum_count_avg](../../../operations/settings/settings.md#optimize_fuse_sum_count_avg)
|
||||
- Настройка [optimize_syntax_fuse_functions](../../../operations/settings/settings.md#optimize_syntax_fuse_functions)
|
||||
|
@ -455,7 +455,7 @@ class IColumn;
|
||||
M(Bool, allow_non_metadata_alters, true, "Allow to execute alters which affects not only tables metadata, but also data on disk", 0) \
|
||||
M(Bool, enable_global_with_statement, true, "Propagate WITH statements to UNION queries and all subqueries", 0) \
|
||||
M(Bool, aggregate_functions_null_for_empty, false, "Rewrite all aggregate functions in a query, adding -OrNull suffix to them", 0) \
|
||||
M(Bool, optimize_fuse_sum_count_avg, false, "Fuse aggregate functions sum(), avg(), count() with identical arguments into one sumCount() call, if the query has at least two different functions", 0) \
|
||||
M(Bool, optimize_syntax_fuse_functions, false, "Fuse aggregate functions (`sum, avg, count` with identical arguments into one `sumCount`, quantile-family functions with the same argument into `quantiles*(...)[...]`)", 0) \
|
||||
M(Bool, flatten_nested, true, "If true, columns of type Nested will be flatten to separate array columns instead of one array of tuples", 0) \
|
||||
M(Bool, asterisk_include_materialized_columns, false, "Include MATERIALIZED columns for wildcard query", 0) \
|
||||
M(Bool, asterisk_include_alias_columns, false, "Include ALIAS columns for wildcard query", 0) \
|
||||
@ -525,6 +525,7 @@ class IColumn;
|
||||
M(HandleKafkaErrorMode, handle_kafka_error_mode, HandleKafkaErrorMode::DEFAULT, "Obsolete setting, does nothing.", 0) \
|
||||
M(Bool, database_replicated_ddl_output, true, "Obsolete setting, does nothing.", 0) \
|
||||
M(UInt64, replication_alter_columns_timeout, 60, "Obsolete setting, does nothing.", 0) \
|
||||
M(Bool, optimize_fuse_sum_count_avg, false, "Obsolete, use optimize_syntax_fuse_functions", 0) \
|
||||
/** The section above is for obsolete settings. Do not add anything there. */
|
||||
|
||||
|
||||
|
83
src/Interpreters/GatherFunctionQuantileVisitor.cpp
Normal file
83
src/Interpreters/GatherFunctionQuantileVisitor.cpp
Normal file
@ -0,0 +1,83 @@
|
||||
#include <string>
|
||||
#include <Interpreters/GatherFunctionQuantileVisitor.h>
|
||||
#include <Common/Exception.h>
|
||||
#include <common/types.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
/// Mapping from quantile functions for single value to plural
|
||||
static const std::unordered_map<String, String> quantile_fuse_name_mapping = {
|
||||
{NameQuantile::name, NameQuantiles::name},
|
||||
{NameQuantileDeterministic::name, NameQuantilesDeterministic::name},
|
||||
{NameQuantileExact::name, NameQuantilesExact::name},
|
||||
{NameQuantileExactLow::name, NameQuantilesExactLow::name},
|
||||
{NameQuantileExactHigh::name, NameQuantilesExactHigh::name},
|
||||
{NameQuantileExactExclusive::name, NameQuantilesExactExclusive::name},
|
||||
{NameQuantileExactInclusive::name, NameQuantilesExactInclusive::name},
|
||||
{NameQuantileExactWeighted::name, NameQuantilesExactWeighted::name},
|
||||
{NameQuantileTiming::name, NameQuantilesTiming::name},
|
||||
{NameQuantileTimingWeighted::name, NameQuantilesTimingWeighted::name},
|
||||
{NameQuantileTDigest::name, NameQuantilesTDigest::name},
|
||||
{NameQuantileTDigestWeighted::name, NameQuantilesTDigestWeighted::name},
|
||||
{NameQuantileBFloat16::name, NameQuantilesBFloat16::name}
|
||||
};
|
||||
|
||||
String GatherFunctionQuantileData::getFusedName(const String & func_name)
|
||||
{
|
||||
if (auto it = quantile_fuse_name_mapping.find(func_name); it != quantile_fuse_name_mapping.end())
|
||||
return it->second;
|
||||
throw DB::Exception(ErrorCodes::LOGICAL_ERROR, "Function '{}' is not quantile-family or cannot be fused", func_name);
|
||||
}
|
||||
|
||||
void GatherFunctionQuantileData::visit(ASTFunction & function, ASTPtr & ast)
|
||||
{
|
||||
if (!quantile_fuse_name_mapping.contains(function.name))
|
||||
return;
|
||||
|
||||
fuse_quantile[function.name].addFuncNode(ast);
|
||||
}
|
||||
|
||||
void GatherFunctionQuantileData::FuseQuantileAggregatesData::addFuncNode(ASTPtr & ast)
|
||||
{
|
||||
const auto * func = ast->as<ASTFunction>();
|
||||
if (!func)
|
||||
return;
|
||||
|
||||
const auto & arguments = func->arguments->children;
|
||||
|
||||
bool need_two_args = func->name == NameQuantileDeterministic::name
|
||||
|| func->name == NameQuantileExactWeighted::name
|
||||
|| func->name == NameQuantileTimingWeighted::name
|
||||
|| func->name == NameQuantileTDigestWeighted::name;
|
||||
if (arguments.size() != (need_two_args ? 2 : 1))
|
||||
return;
|
||||
|
||||
if (arguments[0]->getColumnName().find(',') != std::string::npos)
|
||||
return;
|
||||
String arg_name = arguments[0]->getColumnName();
|
||||
if (need_two_args)
|
||||
{
|
||||
if (arguments[1]->getColumnName().find(',') != std::string::npos)
|
||||
return;
|
||||
arg_name += "," + arguments[1]->getColumnName();
|
||||
}
|
||||
|
||||
arg_map_function[arg_name].push_back(&ast);
|
||||
}
|
||||
|
||||
bool GatherFunctionQuantileData::needChild(const ASTPtr & node, const ASTPtr &)
|
||||
{
|
||||
/// Skip children of quantile* functions to escape cycles in further processing
|
||||
if (const auto * func = node ? node->as<ASTFunction>() : nullptr)
|
||||
return !quantile_fuse_name_mapping.contains(func->name);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
35
src/Interpreters/GatherFunctionQuantileVisitor.h
Normal file
35
src/Interpreters/GatherFunctionQuantileVisitor.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <Parsers/ASTFunction.h>
|
||||
#include <Parsers/IAST.h>
|
||||
#include <Interpreters/InDepthNodeVisitor.h>
|
||||
#include <AggregateFunctions/AggregateFunctionQuantile.h>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
|
||||
/// Gather all the `quantile*` functions
|
||||
class GatherFunctionQuantileData
|
||||
{
|
||||
public:
|
||||
struct FuseQuantileAggregatesData
|
||||
{
|
||||
std::unordered_map<String, std::vector<ASTPtr *>> arg_map_function;
|
||||
|
||||
void addFuncNode(ASTPtr & ast);
|
||||
};
|
||||
|
||||
using TypeToVisit = ASTFunction;
|
||||
|
||||
std::unordered_map<String, FuseQuantileAggregatesData> fuse_quantile;
|
||||
|
||||
void visit(ASTFunction & function, ASTPtr & ast);
|
||||
|
||||
static String getFusedName(const String & func_name);
|
||||
|
||||
static bool needChild(const ASTPtr & node, const ASTPtr &);
|
||||
};
|
||||
|
||||
using GatherFunctionQuantileVisitor = InDepthNodeVisitor<OneTypeMatcher<GatherFunctionQuantileData, GatherFunctionQuantileData::needChild>, true>;
|
||||
|
||||
}
|
@ -18,6 +18,7 @@
|
||||
#include <Interpreters/RewriteFunctionToSubcolumnVisitor.h>
|
||||
#include <Interpreters/Context.h>
|
||||
#include <Interpreters/ExternalDictionariesLoader.h>
|
||||
#include <Interpreters/GatherFunctionQuantileVisitor.h>
|
||||
|
||||
#include <Parsers/ASTExpressionList.h>
|
||||
#include <Parsers/ASTFunction.h>
|
||||
@ -626,6 +627,59 @@ void optimizeFunctionsToSubcolumns(ASTPtr & query, const StorageMetadataPtr & me
|
||||
RewriteFunctionToSubcolumnVisitor(data).visit(query);
|
||||
}
|
||||
|
||||
std::shared_ptr<ASTFunction> getQuantileFuseCandidate(const String & func_name, std::vector<ASTPtr *> & functions)
|
||||
{
|
||||
if (functions.size() < 2)
|
||||
return nullptr;
|
||||
|
||||
const auto & common_arguments = (*functions[0])->as<ASTFunction>()->arguments->children;
|
||||
auto func_base = makeASTFunction(GatherFunctionQuantileData::getFusedName(func_name));
|
||||
func_base->arguments->children = common_arguments;
|
||||
func_base->parameters = std::make_shared<ASTExpressionList>();
|
||||
|
||||
for (const auto * ast : functions)
|
||||
{
|
||||
assert(ast && *ast);
|
||||
const auto * func = (*ast)->as<ASTFunction>();
|
||||
assert(func && func->parameters->as<ASTExpressionList>());
|
||||
const ASTs & parameters = func->parameters->as<ASTExpressionList &>().children;
|
||||
if (parameters.size() != 1)
|
||||
return nullptr; /// query is illegal, give up
|
||||
func_base->parameters->children.push_back(parameters[0]);
|
||||
}
|
||||
return func_base;
|
||||
}
|
||||
|
||||
/// Rewrites multi quantile()() functions with the same arguments to quantiles()()[]
|
||||
/// eg:SELECT quantile(0.5)(x), quantile(0.9)(x), quantile(0.95)(x) FROM...
|
||||
/// rewrite to : SELECT quantiles(0.5, 0.9, 0.95)(x)[1], quantiles(0.5, 0.9, 0.95)(x)[2], quantiles(0.5, 0.9, 0.95)(x)[3] FROM ...
|
||||
void optimizeFuseQuantileFunctions(ASTPtr & query)
|
||||
{
|
||||
GatherFunctionQuantileVisitor::Data data{};
|
||||
GatherFunctionQuantileVisitor(data).visit(query);
|
||||
for (auto & candidate : data.fuse_quantile)
|
||||
{
|
||||
String func_name = candidate.first;
|
||||
auto & args_to_functions = candidate.second;
|
||||
|
||||
/// Try to fuse multiply `quantile*` Function to plural
|
||||
for (auto it : args_to_functions.arg_map_function)
|
||||
{
|
||||
std::vector<ASTPtr *> & functions = it.second;
|
||||
auto func_base = getQuantileFuseCandidate(func_name, functions);
|
||||
if (!func_base)
|
||||
continue;
|
||||
for (size_t i = 0; i < functions.size(); ++i)
|
||||
{
|
||||
std::shared_ptr<ASTFunction> ast_new = makeASTFunction("arrayElement", func_base, std::make_shared<ASTLiteral>(i + 1));
|
||||
if (const auto & alias = (*functions[i])->tryGetAlias(); !alias.empty())
|
||||
ast_new->setAlias(alias);
|
||||
*functions[i] = ast_new;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void TreeOptimizer::optimizeIf(ASTPtr & query, Aliases & aliases, bool if_chain_to_multiif)
|
||||
@ -723,6 +777,9 @@ void TreeOptimizer::apply(ASTPtr & query, TreeRewriterResult & result,
|
||||
|
||||
/// Remove duplicated columns from USING(...).
|
||||
optimizeUsing(select_query);
|
||||
|
||||
if (settings.optimize_syntax_fuse_functions)
|
||||
optimizeFuseQuantileFunctions(query);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1072,7 +1072,7 @@ void TreeRewriter::normalize(
|
||||
// if we have at least two different functions. E.g. we will replace sum(x)
|
||||
// and count(x) with sumCount(x).1 and sumCount(x).2, and sumCount() will
|
||||
// be calculated only once because of CSE.
|
||||
if (settings.optimize_fuse_sum_count_avg)
|
||||
if (settings.optimize_fuse_sum_count_avg || settings.optimize_syntax_fuse_functions)
|
||||
{
|
||||
FuseSumCountAggregatesVisitor::Data data;
|
||||
FuseSumCountAggregatesVisitor(data).visit(query);
|
||||
|
@ -64,6 +64,7 @@ SRCS(
|
||||
ExtractExpressionInfoVisitor.cpp
|
||||
FillingRow.cpp
|
||||
FunctionNameNormalizer.cpp
|
||||
GatherFunctionQuantileVisitor.cpp
|
||||
HashJoin.cpp
|
||||
IExternalLoadable.cpp
|
||||
IInterpreter.cpp
|
||||
|
@ -6,7 +6,7 @@
|
||||
Also test GROUP BY with and without keys, because they might have different
|
||||
optimizations. -->
|
||||
<settings>
|
||||
<optimize_fuse_sum_count_avg>1</optimize_fuse_sum_count_avg>
|
||||
<optimize_syntax_fuse_functions>1</optimize_syntax_fuse_functions>
|
||||
</settings>
|
||||
|
||||
<substitutions>
|
||||
@ -21,13 +21,13 @@
|
||||
|
||||
<query>SELECT sum(number) FROM numbers(1000000000) FORMAT Null</query>
|
||||
<query>SELECT sum(number), count(number) FROM numbers(1000000000) FORMAT Null</query>
|
||||
<query>SELECT sum(number), count(number) FROM numbers(1000000000) SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
|
||||
<query>SELECT sum(number), count(number) FROM numbers(1000000000) SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
|
||||
<query>SELECT sum(number), avg(number), count(number) FROM numbers(1000000000) FORMAT Null</query>
|
||||
<query>SELECT sum(number), avg(number), count(number) FROM numbers(1000000000) SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
|
||||
<query>SELECT sum(number), avg(number), count(number) FROM numbers(1000000000) SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
|
||||
|
||||
<query>SELECT sum(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 FORMAT Null</query>
|
||||
<query>SELECT sum(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 FORMAT Null</query>
|
||||
<query>SELECT sum(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
|
||||
<query>SELECT sum(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
|
||||
<query>SELECT sum(number), avg(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 FORMAT Null</query>
|
||||
<query>SELECT sum(number), avg(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_fuse_sum_count_avg = 0 FORMAT Null</query>
|
||||
<query>SELECT sum(number), avg(number), count(number) FROM numbers(100000000) GROUP BY intHash32(number) % 1000 SETTINGS optimize_syntax_fuse_functions = 0 FORMAT Null</query>
|
||||
</test>
|
||||
|
@ -2,7 +2,7 @@ DROP TABLE IF EXISTS fuse_tbl;
|
||||
CREATE TABLE fuse_tbl(a Int8, b Int8) Engine = Log;
|
||||
INSERT INTO fuse_tbl SELECT number, number + 1 FROM numbers(1, 20);
|
||||
|
||||
SET optimize_fuse_sum_count_avg = 1;
|
||||
SET optimize_syntax_fuse_functions = 1;
|
||||
SELECT sum(a), sum(b), count(b) from fuse_tbl;
|
||||
EXPLAIN SYNTAX SELECT sum(a), sum(b), count(b) from fuse_tbl;
|
||||
SELECT '---------NOT trigger fuse--------';
|
||||
|
@ -0,0 +1,90 @@
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
30000 30000 30000
|
||||
30000 30000 30000
|
||||
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
|
||||
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
|
||||
2016-04-02 17:23:12 2016-04-02 17:23:12 2016-04-02 17:23:12
|
||||
---------After fuse result-----------
|
||||
quantile:
|
||||
SELECT
|
||||
quantiles(0.2, 0.3)(d)[1],
|
||||
quantiles(0.2, 0.3)(d)[2]
|
||||
FROM datetime
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
quantileDeterministic:
|
||||
SELECT
|
||||
quantilesDeterministic(0.2, 0.5)(d, 1)[1],
|
||||
quantilesDeterministic(0.2, 0.5)(d, 1)[2]
|
||||
FROM datetime
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
quantileExact:
|
||||
SELECT
|
||||
quantilesExact(0.2, 0.5)(d)[1],
|
||||
quantilesExact(0.2, 0.5)(d)[2]
|
||||
FROM datetime
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
quantileExactWeighted:
|
||||
SELECT
|
||||
quantilesExactWeighted(0.2, 0.4)(d, 1)[1],
|
||||
quantilesExactWeighted(0.2, 0.4)(d, 1)[2],
|
||||
quantileExactWeighted(0.3)(d, 2)
|
||||
FROM datetime
|
||||
2016-06-15 23:00:00 2016-06-15 23:00:00 2016-06-15 23:00:00
|
||||
quantileTiming:
|
||||
SELECT
|
||||
quantilesTiming(0.2, 0.3)(d)[1],
|
||||
quantilesTiming(0.2, 0.3)(d)[2],
|
||||
quantileTiming(0.2)(d + 1)
|
||||
FROM datetime
|
||||
30000 30000 30000
|
||||
quantileTimingWeighted:
|
||||
SELECT
|
||||
quantilesTimingWeighted(0.2, 0.3)(d, 1)[1],
|
||||
quantilesTimingWeighted(0.2, 0.3)(d, 1)[2],
|
||||
quantileTimingWeighted(0.2)(d, 2)
|
||||
FROM datetime
|
||||
30000 30000 30000
|
||||
quantileTDigest:
|
||||
SELECT
|
||||
quantilesTDigest(0.2, 0.3)(d)[1],
|
||||
quantilesTDigest(0.2, 0.3)(d)[2],
|
||||
quantileTDigest(0.2)(d + 1)
|
||||
FROM datetime
|
||||
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
|
||||
quantileTDigestWeighted:
|
||||
SELECT
|
||||
quantilesTDigestWeighted(0.2, 0.3)(d, 1)[1],
|
||||
quantilesTDigestWeighted(0.2, 0.3)(d, 1)[2],
|
||||
quantileTDigestWeighted(0.4)(d, 2)
|
||||
FROM datetime
|
||||
2016-06-15 23:00:16 2016-06-15 23:00:16 2016-06-15 23:00:16
|
||||
quantileBFloat16:
|
||||
SELECT
|
||||
quantilesBFloat16(0.2, 0.3)(d)[1],
|
||||
quantilesBFloat16(0.2, 0.3)(d)[2],
|
||||
quantileBFloat16(0.4)(d + 1)
|
||||
FROM datetime
|
||||
2016-04-02 17:23:12 2016-04-02 17:23:12 2016-04-02 17:23:12
|
||||
SELECT
|
||||
quantiles(0.2, 0.3, 0.2)(d)[1] AS k,
|
||||
quantiles(0.2, 0.3, 0.2)(d)[2]
|
||||
FROM datetime
|
||||
ORDER BY quantiles(0.2, 0.3, 0.2)(d)[3] ASC
|
||||
0 4 7.2 7.6
|
||||
1 5 8.2 8.6
|
||||
SELECT
|
||||
b,
|
||||
quantiles(0.5, 0.9, 0.95)(x)[1] AS a,
|
||||
quantiles(0.5, 0.9, 0.95)(x)[2] AS y,
|
||||
quantiles(0.5, 0.9, 0.95)(x)[3]
|
||||
FROM
|
||||
(
|
||||
SELECT
|
||||
number AS x,
|
||||
number % 2 AS b
|
||||
FROM numbers(10)
|
||||
)
|
||||
GROUP BY b
|
@ -0,0 +1,68 @@
|
||||
DROP TABLE IF EXISTS datetime;
|
||||
CREATE TABLE datetime (d DateTime('UTC')) ENGINE = Memory;
|
||||
INSERT INTO datetime(d) VALUES(toDateTime('2016-06-15 23:00:00', 'UTC'))
|
||||
|
||||
SELECT quantile(0.2)(d), quantile(0.3)(d) FROM datetime;
|
||||
SELECT quantileDeterministic(0.2)(d, 1), quantileDeterministic(0.5)(d, 1) FROM datetime;
|
||||
SELECT quantileExact(0.2)(d), quantileExact(0.5)(d) FROM datetime;
|
||||
SELECT quantileExactWeighted(0.2)(d, 1), quantileExactWeighted(0.4)(d, 1), quantileExactWeighted(0.3)(d, 2) FROM datetime;
|
||||
SELECT quantileTiming(0.2)(d), quantileTiming(0.3)(d), quantileTiming(0.2)(d+1) FROM datetime;
|
||||
SELECT quantileTimingWeighted(0.2)(d, 1), quantileTimingWeighted(0.3)(d, 1), quantileTimingWeighted(0.2)(d, 2) FROM datetime;
|
||||
SELECT quantileTDigest(0.2)(d), quantileTDigest(0.3)(d), quantileTDigest(0.2)(d + 1) FROM datetime;
|
||||
SELECT quantileTDigestWeighted(0.2)(d, 1), quantileTDigestWeighted(0.3)(d, 1), quantileTDigestWeighted(0.4)(d, 2) FROM datetime;
|
||||
SELECT quantileBFloat16(0.2)(d), quantileBFloat16(0.3)(d), quantileBFloat16(0.4)(d + 1) FROM datetime;
|
||||
|
||||
|
||||
SELECT '---------After fuse result-----------';
|
||||
SET optimize_syntax_fuse_functions = true;
|
||||
SELECT 'quantile:';
|
||||
EXPLAIN SYNTAX SELECT quantile(0.2)(d), quantile(0.3)(d) FROM datetime;
|
||||
SELECT quantile(0.2)(d), quantile(0.3)(d) FROM datetime;
|
||||
|
||||
SELECT 'quantileDeterministic:';
|
||||
EXPLAIN SYNTAX SELECT quantileDeterministic(0.2)(d, 1), quantileDeterministic(0.5)(d, 1) FROM datetime;
|
||||
SELECT quantileDeterministic(0.2)(d, 1), quantileDeterministic(0.5)(d, 1) FROM datetime;
|
||||
|
||||
SELECT 'quantileExact:';
|
||||
EXPLAIN SYNTAX SELECT quantileExact(0.2)(d), quantileExact(0.5)(d) FROM datetime;
|
||||
SELECT quantileExact(0.2)(d), quantileExact(0.5)(d) FROM datetime;
|
||||
|
||||
SELECT 'quantileExactWeighted:';
|
||||
EXPLAIN SYNTAX SELECT quantileExactWeighted(0.2)(d, 1), quantileExactWeighted(0.4)(d, 1), quantileExactWeighted(0.3)(d, 2) FROM datetime;
|
||||
SELECT quantileExactWeighted(0.2)(d, 1), quantileExactWeighted(0.4)(d, 1), quantileExactWeighted(0.3)(d, 2) FROM datetime;
|
||||
|
||||
SELECT 'quantileTiming:';
|
||||
EXPLAIN SYNTAX SELECT quantileTiming(0.2)(d), quantileTiming(0.3)(d), quantileTiming(0.2)(d+1) FROM datetime;
|
||||
SELECT quantileTiming(0.2)(d), quantileTiming(0.3)(d), quantileTiming(0.2)(d+1) FROM datetime;
|
||||
|
||||
SELECT 'quantileTimingWeighted:';
|
||||
EXPLAIN SYNTAX SELECT quantileTimingWeighted(0.2)(d, 1), quantileTimingWeighted(0.3)(d, 1), quantileTimingWeighted(0.2)(d, 2) FROM datetime;
|
||||
SELECT quantileTimingWeighted(0.2)(d, 1), quantileTimingWeighted(0.3)(d, 1), quantileTimingWeighted(0.2)(d, 2) FROM datetime;
|
||||
|
||||
SELECT 'quantileTDigest:';
|
||||
EXPLAIN SYNTAX SELECT quantileTDigest(0.2)(d), quantileTDigest(0.3)(d), quantileTDigest(0.2)(d + 1) FROM datetime;
|
||||
SELECT quantileTDigest(0.2)(d), quantileTDigest(0.3)(d), quantileTDigest(0.2)(d + 1) FROM datetime;
|
||||
|
||||
SELECT 'quantileTDigestWeighted:';
|
||||
EXPLAIN SYNTAX SELECT quantileTDigestWeighted(0.2)(d, 1), quantileTDigestWeighted(0.3)(d, 1), quantileTDigestWeighted(0.4)(d, 2) FROM datetime;
|
||||
SELECT quantileTDigestWeighted(0.2)(d, 1), quantileTDigestWeighted(0.3)(d, 1), quantileTDigestWeighted(0.4)(d, 2) FROM datetime;
|
||||
|
||||
SELECT 'quantileBFloat16:';
|
||||
EXPLAIN SYNTAX SELECT quantileBFloat16(0.2)(d), quantileBFloat16(0.3)(d), quantileBFloat16(0.4)(d + 1) FROM datetime;
|
||||
SELECT quantileBFloat16(0.2)(d), quantileBFloat16(0.3)(d), quantileBFloat16(0.4)(d + 1) FROM datetime;
|
||||
|
||||
EXPLAIN SYNTAX SELECT quantile(0.2)(d) as k, quantile(0.3)(d) FROM datetime order by quantile(0.2)(d);
|
||||
|
||||
SELECT b, quantile(0.5)(x) as a, quantile(0.9)(x) as y, quantile(0.95)(x) FROM (select number as x, number % 2 as b from numbers(10)) group by b;
|
||||
EXPLAIN SYNTAX SELECT b, quantile(0.5)(x) as a, quantile(0.9)(x) as y, quantile(0.95)(x) FROM (select number as x, number % 2 as b from numbers(10)) group by b;
|
||||
|
||||
-- fuzzer
|
||||
SELECT quantileDeterministic(0.99)(1023) FROM datetime FORMAT Null; -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT quantileTiming(0.5)(NULL, NULL, quantileTiming(-inf)(NULL), NULL) FROM datetime FORMAT Null; -- { serverError ILLEGAL_AGGREGATION }
|
||||
SELECT quantileTDigest(NULL)(NULL, quantileTDigest(3.14)(NULL, d + NULL), 2.), NULL FORMAT Null; -- { serverError ILLEGAL_AGGREGATION }
|
||||
SELECT quantile(1, 0.3)(d), quantile(0.3)(d) FROM datetime; -- { serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH }
|
||||
SELECT quantile(quantileDeterministic('', '2.47')('0.02', '0.2', NULL), 0.9)(d), quantile(0.3)(d) FROM datetime; -- { serverError ILLEGAL_AGGREGATION }
|
||||
SELECT quantileTimingWeighted([[[[['-214748364.8'], NULL]], [[[quantileTimingWeighted([[[[['-214748364.8'], NULL], '-922337203.6854775808'], [[['-214748364.7']]], NULL]])([NULL], NULL), '-214748364.7']]], NULL]])([NULL], NULL); -- { serverError ILLEGAL_AGGREGATION }
|
||||
SELECT quantileTimingWeighted([quantileTimingWeighted(0.5)(1, 1)])(1, 1); -- { serverError ILLEGAL_AGGREGATION }
|
||||
|
||||
DROP TABLE datetime;
|
Loading…
Reference in New Issue
Block a user