ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Apache Druid DataSketches Quantiles 模块:DoublesSketch 分位数草图聚合器与后聚合器实战指南

Apache Druid DataSketches Quantiles 模块:DoublesSketch 分位数草图聚合器与后聚合器实战指南 数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载本文围绕 Apache Druid 的druid-datasketches扩展中的 Quantiles Sketch 模块展开系统讲解基于 Apache DataSketchesDoublesSketch的分位数近似聚合能力如何加载扩展、如何在摄入阶段或查询阶段构建草图、如何通过六个后聚合器求解分位数、直方图、Rank 与 CDF以及 SQL 层面的APPROX_QUANTILE_DS用法。读完本文你将掌握在大规模数值分布场景下用固定内存近似回答中位数、95 分位、P99等问题的完整落地姿势。DoublesSketch 分位数草图模块定位与三种使用模式Quantiles Sketch 模块是 DataSketches 扩展 的一部分为 Apache Druid 提供基于数值分位数DoublesSketch的聚合器。DoublesSketch是一种可合并mergeable的流式算法数据结构它可以一边流式摄入数值一边维护一个紧凑的分布摘要从而近似回答以下四类问题Rank某个值在分布中的排名小于该值的占比PMF / 直方图Probability Mass Function分布的概率质量函数即各区间内值的占比CDFCumulative Distribution Function累积分布函数Quantiles分位数如中位数、最小值、最大值、95 百分位等。与精确排序/存储全量数据不同DoublesSketch以固定或近固定的内存换精度特别适合 Druid 这种海量行、常驻 Segment、查询需快速合并的分析场景。从源码看该模块的核心实现位于 extensions-core/datasketches/src/main/java/org/apache/druid/query/aggregation/datasketches/quantiles 目录包括聚合器工厂、构建/合并聚合器、六个后聚合器与 SQL 集成类。官方定义该模块支持三种主要操作模式摄入 Druid 外部构建好的草图例如用 Pig 或 Hive 预构建的 sketch以二进制列的形式摄入摄入时从原始数据构建草图把原始数值列在 ingestion 阶段就地转成 sketch 存储为复杂列查询时从原始数据构建草图Segment 里存的是普通数值查询时临时构建 sketch 完成分位数计算。这三种模式在同一份聚合器配置下由 Druid 自动判别聚合器工厂会根据fieldName指向列的ColumnCapabilities是否为数值类型来决定是构建还是合并这一点在 DoublesSketchAggregatorFactory.factorize() 中体现得很直接——数值列走DoublesSketchBuildAggregatorsketch 复杂列走DoublesSketchMergeAggregator空列则退化为NoopDoublesSketchAggregator。加载扩展要使用本模块首先需要在配置文件common.runtime.properties等中把druid-datasketches加入扩展加载列表参见 加载扩展druid.extensions.loadList[druid-datasketches]druid-datasketches扩展包含 Theta、Tuple、Quantiles本文、KLL Quantiles、HLL 等多种草图模块详见 DataSketches extension。扩展加载后DoublesSketchModule 会通过 Jackson 注册所有聚合器/后聚合器类型并注册 complex 列的 Serde 与 SQL 绑定因此 JSON 查询与 SQL 查询均可直接使用。AggregatorquantilesDoublesSketch聚合的产物是一个DoublesSketch——它要么由原始数据构建要么从 Segment 中读取后与其他 sketch 做 union 合并。基本配置如下{ type : quantilesDoublesSketch, name : output_name, fieldName : metric_name, k: parameter that controls size and accuracy }Property说明是否必填type固定为quantilesDoublesSketch是name输出列名用于存放 sketch 值是fieldName输入字段名可以是已构建的 sketch 列也可以是原始数值列是k控制草图精度与大小的参数。k越大精度越高、占用的存储空间越大。必须为 2 到 32768 之间的 2 的幂。精度详情可参考 DataSketches 官方 QuantilesSketch 精度文档否默认 128maxStreamLength每个 sketch 在从 off-heap 迁移到 on-heap 内存之前可容纳的数据项数上限。该参数对使用 off-heap 内存的查询类型包括 TopN 和 GroupBy有意义建议设置得足够大使大多数 sketch 能保持在 off-heap否默认 1000000000shouldFinalize为true时返回最终 double 类型的估计值而非中间的 sketch 对象本身。除了控制该聚合器自身的 finalization还可以通过查询上下文参数finalize和sqlFinalizeOuterSketches统一控制所有聚合器是否被 finalize否默认true源码层面的参数语义k 的合法性校验在 DoublesSketchAggregatorFactory 构造器 中k为空时取默认值 128随后调用 DataSketches 的Util.checkIfIntPowerOf2(k, k)强制校验k必须是 2 的幂否则直接抛出异常——这与文档中2 的幂、2 到 32768的约束一一对应。默认值常量DEFAULT_K 128、DEFAULT_SHOULD_FINALIZE true、DEFAULT_MAX_STREAM_LENGTH 1_000_000_000均定义在该工厂类中与文档参数表一致。finalize 行为finalizeComputation()在shouldFinalize true时返回sketch.getN()即 sketch 中已摄入的数据项总数long 类型否则原样返回 sketch 对象。因此shouldFinalize为true时聚合结果类型是LONG为false时是DOUBLES_SKETCH复杂类型。合并语义getMergingFactory()支持不同k的 sketch 合并——DoublesUnion的结果有效k会落在指定 k 与所有输入 sketch 的最小 k 之间尽量保留更高精度。内存估算getMaxIntermediateSize()用DoublesSketch.getUpdatableStorageBytes(k, maxStreamLength)估算中间态占用的最大字节数。源码注释特别说明quantiles sketch 永远不会停止增长但增长非常缓慢因此该尺寸只对绝大多数 sketch 足够个别 sketch 可能在运行期申请更多堆内存并迁移到 on-heap——这正是maxStreamLength参数要权衡的点。shouldFinalizefalse 的使用场景当你希望把 sketch 作为中间结果继续参与后聚合运算如先对一批数据构建 sketch再在查询中求多个分位数/直方图应关闭 finalize 并配合后聚合器使用若只需一个最终数值保持默认true即可。三种构建模式实战从测试用例看配置形态仓库中的集成测试 DoublesSketchAggregatorTest 完整覆盖了三种模式可以直接作为配置范本。模式一摄入外部预构建的 sketch测试ingestingSketches演示了把 TSV 中已序列化的 sketch 列配合doubles_sketch_data.tsv测试数据直接摄入查询时再用quantilesDoublesSketch聚合器做合并{ queryType: groupBy, dataSource: test_datasource, granularity: ALL, dimensions: [], aggregations: [ {type: quantilesDoublesSketch, name: sketch, fieldName: sketch, k: 128}, {type: quantilesDoublesSketch, name: non_existent_sketch, fieldName: non_existent_sketch, k: 128} ], postAggregations: [ {type: quantilesDoublesSketchToQuantiles, name: quantiles, fractions: [0, 0.5, 1], field: {type: fieldAccess, fieldName: sketch}}, {type: quantilesDoublesSketchToHistogram, name: histogram, splitPoints: [0.25, 0.5, 0.75], field: {type: fieldAccess, fieldName: sketch}} ], intervals: [2016-01-01T00:00:00.000Z/2016-01-31T00:00:00.000Z] }测试断言 400 条数据合并后 sketch 的getN()为 400且fractions[0, 0.5, 1]对应的分位数分别近似 0、0.5、1误差 ±0.05。模式二摄入时从原始数据构建测试buildingSketchesAtIngestionTime把原始数值列value在摄入索引阶段就地构建成 sketch摄入 spec 中直接写{type: quantilesDoublesSketch, name: sketch, fieldName: value, k: 128}。该模式最适合热数据频繁写入、分位数查询也频繁的场景代价是 Segment 中多存一个复杂列。模式三查询时从原始数据构建测试buildingSketchesAtQueryTime的 Segment 中只有普通的doubleSum指标查询时再对数值列临时构建 sketch。该模式不增加 Segment 体积但每次查询都要扫描原始数值构建草图适合对延迟不敏感、存储优先的场景。三种模式共用同一套聚合器/后聚合器 JSONDruid 依据列类型自动分流极大简化了配置切换成本。Post aggregators把 sketch 变成可读结果后聚合器的field既可以是一个fieldAccess引用 sketch 聚合结果也可以是另一个后聚合器支持级联。所有类型名注册于 DoublesSketchModule 中。Quantile单一分位数返回假设输入流已排序时给定占比之前的值的近似值即fraction对应的分位数。{ type : quantilesDoublesSketchToQuantile, name: output name, field : post aggregator that refers to a DoublesSketch (fieldAccess or another post aggregator), fraction : fractional position in the hypothetical sorted stream, number from 0 to 1 inclusive }对应实现 DoublesSketchToQuantilePostAggregator.compute()空 sketch 返回Double.NaN否则返回sketch.getQuantile(fraction)结果类型为DOUBLE。fraction取值区间为闭区间 [0, 1]。Quantiles多个分位数一次返回与fractions数组一一对应的分位数数组。{ type : quantilesDoublesSketchToQuantiles, name: output name, field : post aggregator that refers to a DoublesSketch (fieldAccess or another post aggregator), fractions : array of fractional positions in the hypothetical sorted stream, number from 0 to 1 inclusive }结果类型为double[]例如[0, 0.5, 1]对应最小值、中位数、最大值。上面的测试用例正是用它验证了 400 条均匀分布数据的分位数。Histogram直方图给定一组 split points分箱切点或箱数二选一不可同时指定返回各箱的近似计数count而非占比。m个互不相同且单调递增的切点把实数轴划分为m1个连续不相交的区间区间定义为左闭右开含左切点、不含右切点。若指定箱数而非切点则把最小值与最大值之间的区间等分为指定数量的箱。{ type : quantilesDoublesSketchToHistogram, name: output name, field : post aggregator that refers to a DoublesSketch (fieldAccess or another post aggregator), splitPoints : array of split points (optional), numBins : number of bins (optional, defaults to 10) }实现细节见 DoublesSketchToHistogramPostAggregatorsplitPoints与numBins同时给出会直接抛出IAE两者都未给出时numBins默认 10箱数必须至少为 2numBins 2抛异常空 sketch 返回长度numBins、元素全为NaN的数组当min max所有值相同时无法生成等距切点此时所有计数归入第一个桶、其余桶为 0底层调用sketch.getPMF(splitPoints)得到各区间占比再乘以sketch.getN()缩放为真实计数结果类型为DOUBLE_ARRAY且不支持直方图比较getComparator()直接抛异常。Rank值的排名返回给定值的近似 rank即分布中小于该值的占比。{ type : quantilesDoublesSketchToRank, name: output name, field : post aggregator that refers to a DoublesSketch (fieldAccess or another post aggregator), value : value }CDF累积分布函数给定一组定义箱边界的切点返回 CDF 的近似值。同样m个互不相同且单调递增的切点划分出m1个左闭右开区间结果数组可以理解为每个切点处的 rank且末尾额外附带一个恒为 1 的 rank即全部数据占比 1。{ type : quantilesDoublesSketchToCDF, name: output name, field : post aggregator that refers to a DoublesSketch (fieldAccess or another post aggregator), splitPoints : array of split points }Sketch summary调试用草图摘要返回 sketch 的摘要信息即调用toString()方法的结果包含k、n、最小/最大值等内部状态常用于调试与排查。{ type : quantilesDoublesSketchToString, name: output name, field : post aggregator that refers to a DoublesSketch (fieldAccess or another post aggregator) }SQL 集成APPROX_QUANTILE_DS 与操作符转换除了原生 JSON 查询该模块还提供了完整的 SQL 支持。从 DoublesSketchModule.configure() 可以看到它注册了两个 SQL 聚合器DoublesSketchApproxQuantileSqlAggregator、DoublesSketchObjectSqlAggregator六个操作符转换Operator Conversion把 SQL 函数映射到原生后聚合器Quantile、Quantiles、Histogram、Rank、CDF、Summary。APPROX_QUANTILE_DS(column, probability[, k])SQL 聚合函数APPROX_QUANTILE_DS是原生quantilesDoublesSketch聚合器 quantilesDoublesSketchToQuantile后聚合器的组合封装。签名见 DoublesSketchApproxQuantileSqlAggregatorAPPROX_QUANTILE_DS(column, probability [, k])column输入数值列probability分位概率必须是字面量literal否则无法完成计划toDruidAggregation直接返回 nullk可选分辨率参数也必须是字面量缺省取DEFAULT_K 128。SQL 测试 DoublesSketchSqlAggregatorTest 中的用法示例SELECT APPROX_QUANTILE_DS(m1, 0.01), APPROX_QUANTILE_DS(m1, 0.5, 64), APPROX_QUANTILE_DS(m1, 0.98, 256), APPROX_QUANTILE_DS(m1, 0.99) FROM ...查询上下文控制 sketch 的 finalization 与内存原生 JSON 查询中可用查询上下文参数finalize统一控制所有聚合器是否 finalizeSQL 查询中可用sqlFinalizeOuterSketches控制外层 sketch 的 finalizeSQL 场景下APPROX_QUANTILE_DS还有专属上下文参数approxQuantileDsMaxStreamLength定义于 DoublesSketchApproxQuantileSqlAggregator用于覆写maxStreamLength的默认值1_000_000_000从而控制 sketch 在 off-heap 与 on-heap 之间的驻留策略。精度、k 与内存的权衡建议k是 Quantiles Sketch 最核心的调参旋钮直接影响精度-空间的平衡精度k越大getQuantile/getRank/getPMF等查询的近似误差上界越小。DataSketches 官方文档给出了各k下的归一化秩误差normalized rank error参考值选型时可直接查阅其 QuantilesSketch 精度文档。空间sketch 的存储大小随k线性增长。k128默认通常能覆盖绝大多数业务场景对精度敏感如金融风控分位阈值可上调到 256/512对海量列且存储敏感的场景可下调到 64。约束k必须是 2 的幂且落在 [2, 32768] 区间内非法取值会在聚合器构造阶段直接报错。maxStreamLength 与内存由于 sketch 的中间态内存按DoublesSketch.getUpdatableStorageBytes(k, maxStreamLength)预分配maxStreamLength设置过小会导致 sketch 提前从 off-heap 迁往 on-heap拖慢 TopN/GroupBy 等依赖 off-heap 内存的查询设置过大则浪费预留内存。默认1_000_000_000对绝大多数场景是安全选择按数据规模微调即可。与同扩展其他草图模块的关系Quantiles 模块只是druid-datasketches的一个子模块。若你追求更高精度/更紧凑的 sketch可参考 DataSketches extension 中提到的 KLL Quantiles Sketch相同精度下更紧凑或相同大小下更精确等其他模块而 distinct count、集合运算、多值关联等场景则分别由 Theta、Tuple、HLL 模块覆盖。它们共享同一套构建/合并/后聚合/SQL的接入范式迁移成本很低。参考与延伸阅读模块文档原文DataSketches Quantiles Sketch module扩展总览与其余草图模块DataSketches extension扩展加载配置extensions.md查询上下文参数query-context.md、sql-query-context.md涉及 off-heap 内存的查询类型TopN、GroupBy核心源码DoublesSketchAggregatorFactory、DoublesSketchModule三种模式与 SQL 的测试用例DoublesSketchAggregatorTest、DoublesSketchSqlAggregatorTest赞分享数据库OLAP大数据后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid6/druid点击查看免费下载相关推荐Apache Druid DataSketches Tuple 模块实战ArrayOfDoublesSketch 聚合器与后聚合器完全指南Apache Druid DataSketches Tuple 模块实战ArrayOfDoublesSketch 聚合器与后聚合器完全指南 本篇指南以 Apa数据库OLAP大数据后端Apache Druid KLL Quantiles Sketch 聚合器实战指南Apache Druid KLL Quantiles Sketch 聚合器实战指南 本文以 Apache Druid 官方扩展 druid datasketch数据库OLAP大数据后端Apache Druid T-Digest Quantiles Sketch 扩展近似分位数聚合与实战指南Apache Druid T Digest Quantiles Sketch 扩展近似分位数聚合与实战指南 T Digest Quantiles Sketch数据库OLAP大数据后端上一篇AgentScope 2.0 多智能体框架完整指南事件流、权限引擎与沙箱工作区实践下一篇StarRocks 实时数据同步实战使用 BladePipe 将数据库与消息队列数据同步至 StarRocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表