From ddf3839306081bb1aba24b9c42ee43ef9d7a50d1 Mon Sep 17 00:00:00 2001 From: coderashed Date: Mon, 29 Jun 2026 22:26:34 +0000 Subject: [PATCH 1/3] feat(aggregate-functions): add quantileReq for relative-error quantiles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add `quantileReq`, `quantilesReq`, and the `medianReq` alias: a streaming quantile based on the Relative Error Quantiles (REQ) sketch from the bundled DataSketches library. Unlike `quantileTDigest` (no formal error bound) and `quantileGK` (flat rank-error bound), REQ guarantees a relative rank error, so it stays accurate at extreme quantiles such as p99.9. The sketch is fully mergeable, so it works under partial and distributed aggregation. Reference: Cormode, Karnin, Liberty, Thaler, Veselý, "Relative Error Streaming Quantiles" (JACM 2023, https://dl.acm.org/doi/10.1145/3617891). --- contrib/datasketches-cpp-cmake/CMakeLists.txt | 1 + .../reference/quantileReq.md | 14 ++ .../AggregateFunctionQuantile.h | 4 + .../AggregateFunctionQuantileReq.cpp | 114 +++++++++++++ src/AggregateFunctions/QuantileReq.h | 154 ++++++++++++++++++ .../registerAggregateFunctions.cpp | 2 + .../GatherFunctionQuantileVisitor.cpp | 1 + .../0_stateless/04489_quantile_req.reference | 9 + .../0_stateless/04489_quantile_req.sql | 57 +++++++ 9 files changed, 356 insertions(+) create mode 100644 docs/en/sql-reference/aggregate-functions/reference/quantileReq.md create mode 100644 src/AggregateFunctions/AggregateFunctionQuantileReq.cpp create mode 100644 src/AggregateFunctions/QuantileReq.h create mode 100644 tests/queries/0_stateless/04489_quantile_req.reference create mode 100644 tests/queries/0_stateless/04489_quantile_req.sql diff --git a/contrib/datasketches-cpp-cmake/CMakeLists.txt b/contrib/datasketches-cpp-cmake/CMakeLists.txt index 497d6956d0ef..72327b56f8a9 100644 --- a/contrib/datasketches-cpp-cmake/CMakeLists.txt +++ b/contrib/datasketches-cpp-cmake/CMakeLists.txt @@ -10,6 +10,7 @@ add_library(_datasketches INTERFACE) target_include_directories(_datasketches SYSTEM BEFORE INTERFACE "${ClickHouse_SOURCE_DIR}/contrib/datasketches-cpp/common/include" "${ClickHouse_SOURCE_DIR}/contrib/datasketches-cpp/count/include" + "${ClickHouse_SOURCE_DIR}/contrib/datasketches-cpp/req/include" "${ClickHouse_SOURCE_DIR}/contrib/datasketches-cpp/theta/include") add_library(ch_contrib::datasketches ALIAS _datasketches) diff --git a/docs/en/sql-reference/aggregate-functions/reference/quantileReq.md b/docs/en/sql-reference/aggregate-functions/reference/quantileReq.md new file mode 100644 index 000000000000..e9aaa5e9e464 --- /dev/null +++ b/docs/en/sql-reference/aggregate-functions/reference/quantileReq.md @@ -0,0 +1,14 @@ +--- +description: 'Computes an approximate quantile of a sample using the Relative Error Quantiles (REQ) sketch, with a relative rank-error guarantee that stays accurate at extreme quantiles.' +slug: /sql-reference/aggregate-functions/reference/quantilereq +title: 'quantileReq' +doc_type: 'reference' +--- + + + + +**See Also** + +- [median](/sql-reference/aggregate-functions/reference/median) +- [quantiles](../../../sql-reference/aggregate-functions/reference/quantiles.md) diff --git a/src/AggregateFunctions/AggregateFunctionQuantile.h b/src/AggregateFunctions/AggregateFunctionQuantile.h index d143211b60cb..ae40eb002417 100644 --- a/src/AggregateFunctions/AggregateFunctionQuantile.h +++ b/src/AggregateFunctions/AggregateFunctionQuantile.h @@ -29,6 +29,7 @@ namespace ErrorCodes template class QuantileTiming; template class QuantileGK; template class QuantileDD; +template class QuantileReq; /** Generic aggregate function for calculation of quantiles. * It depends on quantile calculation data structure. Look at Quantile*.h for various implementations. @@ -346,6 +347,9 @@ struct NameQuantilesGK { static constexpr auto name = "quantilesGK"; }; struct NameQuantileDD { static constexpr auto name = "quantileDD"; }; struct NameQuantilesDD { static constexpr auto name = "quantilesDD"; }; +struct NameQuantileReq { static constexpr auto name = "quantileReq"; }; +struct NameQuantilesReq { static constexpr auto name = "quantilesReq"; }; + struct NameQuantilePrometheusHistogram { static constexpr auto name = "quantilePrometheusHistogram"; }; struct NameQuantilesPrometheusHistogram { static constexpr auto name = "quantilesPrometheusHistogram"; }; diff --git a/src/AggregateFunctions/AggregateFunctionQuantileReq.cpp b/src/AggregateFunctions/AggregateFunctionQuantileReq.cpp new file mode 100644 index 000000000000..e468ad460a5a --- /dev/null +++ b/src/AggregateFunctions/AggregateFunctionQuantileReq.cpp @@ -0,0 +1,114 @@ +#include "config.h" + +#include +#include + +#if USE_DATASKETCHES +#include +#include +#include +#include +#include +#endif + + +namespace DB +{ +struct Settings; + +#if USE_DATASKETCHES + +namespace ErrorCodes +{ + extern const int TOO_FEW_ARGUMENTS_FOR_FUNCTION; + extern const int ILLEGAL_TYPE_OF_ARGUMENT; +} + +namespace +{ + +template using FuncQuantileReq = AggregateFunctionQuantile, NameQuantileReq, void, std::conditional_t, false, true>; +template using FuncQuantilesReq = AggregateFunctionQuantile, NameQuantilesReq, void, std::conditional_t, true, true>; + + +template