ARTICLE DETAIL

资讯详情

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

Druid 与 Kudu 对比分析:面向 OLAP 的预聚合列式存储与面向 OLTP 的可更新行式存储

Druid 与 Kudu 对比分析:面向 OLAP 的预聚合列式存储与面向 OLTP 的可更新行式存储 数据库数据分析OLAP大数据实时分析数据仓库后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid7/druid点击查看免费下载Druid 与 Kudu 是两类设计哲学截然不同的数据存储系统Druid 以不可变分段immutable segment 摄入时预聚合rollup 位图索引为核心为 OLAP 聚合查询而优化Kudu 则以行级更新 任意主键 范围查找为核心更贴近传统数据库的 OLTP 特性。本文基于 Apache Druid 官方文档中的对比说明结合本仓库的源码与配套文档逐项拆解两者在更新能力、存储组织、查询执行、生态定位上的本质差异帮助读者根据工作负载特征做出合理的技术选型。一、核心差异总览Druid vs Kudu 对比文档 开篇即点明两者最根本的分歧Kudu 的存储格式支持单行更新而 Druid 对已有 segment 的更新必须重建 segment。这一差异看似让 Druid 在更新旧值的场景下延迟更高但 Kudu 为支持更新付出的代价——预留额外的 head space 存储更新记录、按 id 而非时间组织数据——会在查询时引入额外延迟并迫使系统扫描到那些与当前查询无关的数据。两者在以下维度上走向了截然相反的方向维度Apache DruidApache Kudu数据更新追加极快更新旧数据延迟高需重建 segment支持任意行更新与删除数据组织按时间分区组织 segment支持任意主键按主键组织摄入处理摄入时 rollup 预聚合压缩存储体积保留原始行不做预聚合索引能力维度列携带位图索引inverted index无位图索引支持查询执行自带查询层可下推聚合与计算到数据节点不提供执行引擎依赖外部框架MR、Spark、SQL做节点本地处理典型场景事件流数据的 OLAP 聚合分析需要行级更新与主键查找的混合工作负载二、更新模型不可变分段 vs 行级更新2.1 Druid不可变 segment 与追加优先Druid 将索引存储在segment 文件中并按时间分区Segments 设计文档。segment 一旦生成即为不可变数据对旧数据的修改必须重建merge/re-indexsegment 才能生效。在代码层面segment 的合并与重建由 IndexMerger.java 负责——它将多个 index 合并时依据rollup标志决定是否执行聚合且如果原始 index 已经 rollup 过则无需再次 rollup见 IndexMerger.java#L193-L194// if index is not rolled up, then it should be not rollup here // if index is rolled up, then it is no need to rollup again.这种设计并非缺陷而是刻意为之Druid 擅长处理的是事件数据event data这类数据基本只追加、很少修改。由于 segment 不可变追加新数据只需生成新 segment 即可因此追加append在 Druid 中极快而重建旧 segment 属于高延迟操作只能作为低频运维手段。官方对更新旧数据的方案如批量重灌、insert-segment-to-db等也在 更新已有数据 中单独成文说明 Druid 将更新视为需要显式规划的特殊流程。2.2 Kudu行级更新与主键约束Kudu 则把行级更新作为一等公民数据按主键组织支持任意主键与唯一性约束uniqueness constraints并能在主键范围上做高效查找。为承载更新Kudu 需要在存储中预留额外空间head space存放更新记录同时按 id 而非时间组织数据。这意味着查询一个时间范围时Kudu 需要访问的数据可能横跨多个按 id 分布的数据块更新记录的存在使存储布局比纯追加式更复杂可能引入额外 I/O 与扫描成本。从仓库证据看Druid 侧没有任何面向行级更新的存储结构——segment 文件version.bin、meta.smoosh、XXXXX.smoosh见 Segments 设计文档只描述静态列式数据。Kudu 的行更新能力属于其自身设计不在此仓库范围内本文仅依据对比文档的官方表述展开。三、存储组织时间分区 预聚合 vs 主键组织3.1 Druid 的 rollup摄入时预聚合最高可压缩数十倍对比文档给出了一个重要结论Druid 在摄入时对数据做 summarize/rollup实践中平均可将原始数据量减少最多 40 倍从而显著提升原始数据的扫描性能。这是 Druid 面向 OLAP 的核心武器。rollup 是 Druid 的默认行为。在源码中IncrementalIndexSchema.java 定义了DEFAULT_ROLLUP true且 Builder 默认this.rollup true见 IncrementalIndexSchema.java#L34 与 IncrementalIndexSchema.java#L114。也就是说在相同时间粒度queryGranularity内、维度值完全相同的多行原始数据会在摄入时被合并为一行并对度量列执行预定义聚合如count、doubleSum例如metricsSpec : [ { type : count, name : count }, { type : doubleSum, name : added, fieldName : added }, { type : doubleSum, name : deleted, fieldName : deleted } ], granularitySpec : { type : uniform, segmentGranularity : DAY, queryGranularity : NONE, intervals : [ 2013-08-31/2013-09-01 ] }完整任务示例见 批式摄入文档。granularitySpec中的segmentGranularity决定 segment 按什么时间粒度切分queryGranularity决定 rollup 时聚合的时间桶粒度——这两者共同决定了数据能被压缩到什么程度。需要强调的是rollup 是有取舍的一旦聚合原始明细行即被丢弃除非把聚合粒度设为 NONE 或保留明细维度后续查询将无法下钻到被聚合掉的粒度。Kudu 不做预聚合保留原始行这使它能服务任意粒度的点查与更新但代价是存储与扫描成本更高。对比文档中Druid 平均压缩 40 倍的表述是官方对实际工作负载的观测结论并非所有数据集都能达到这一比例实际压缩率取决于数据的时间局部性、维度重复度与聚合粒度设置。3.2 Kudu按主键组织范围查找高效Kudu 的数据布局以主键为锚任意主键 唯一性约束保证了行级写入的正确性按主键范围range的查找可以快速定位目标数据。这一能力与 Druid 的按时间分区完全不同——Druid 的 segment 标识本身就是datasource_intervalStart_intervalEnd_version_partitionNum见 Segments 设计文档一切查询路径都以时间轴为入口。四、索引与扫描位图索引 vs 无位图支持对比文档明确指出Druid 的 segment 携带位图索引bitmap index用于快速过滤而 Kudu 目前不支持位图索引。Druid 的维度列在 segment 内由三部分构成见 Segments 设计文档字典dictionary将维度值字符串映射为整数 ID列数据column data用字典编码后的值列表支撑 groupBy / TopN 查询位图bitmap对每个唯一值维护一个 bitmap标记哪些行包含该值即倒排索引用于 AND/OR 等快速过滤。在代码层面BitmapIndex.java 定义了这一接口getCardinality()返回维度基数getIndex(String value)以二分查找方式定位值getBitmap(int idx)返回对应唯一值的ImmutableBitmap。由于 bitmap 按行标记命中过滤Filter可以直接基于位运算完成聚合查询若只需按过滤条件聚合度量甚至无需触碰维度值列表本身。public interface BitmapIndex { public int getCardinality(); public String getValue(int index); public boolean hasNulls(); public int getIndex(String value); // 返回该值在字典中的下标 public ImmutableBitmap getBitmap(int idx); // 返回该值对应的行位图 }位图在超高基数维度下会变得稀疏Druid 借助专门针对位图设计的压缩算法如 Roaring Bitmap将稀疏位图压缩到可接受的大小见 Segments 设计文档。Kudu 不提供位图索引其过滤能力更多依赖主键范围扫描与列式存储本身的局部性。五、查询执行内置查询层 vs 依赖外部执行引擎5.1 Druid自带查询层聚合下推到数据节点对比文档指出Druid 包含自己的查询层可以把聚合与计算直接下推到数据节点执行以获得更快的查询处理速度。这也是 Druid 的查询服务器 数据服务器架构的基础——Broker 接收查询、拆分下发Historical/Realtime 节点在本地 segment 上执行过滤、聚合、groupBy 等操作最后汇总返回。以 groupBy 为例groupBy 查询文档一个典型的 OLAP 查询对象包含queryType恒为groupBy、dimensions分组维度、aggregations聚合函数如count、doubleSum与可选的postAggregations。这套查询 DSL 配合 rollup 后的紧凑数据与位图索引构成了 Druid 面向聚合工作负载的完整链路{ queryType: groupBy, dataSource: sample_datasource, granularity: all, dimensions: [ country ], aggregations: [ { type: count, name: rows }, { type: longSum, name: total_usage, fieldName: usage } ] }5.2 Kudu不内置执行引擎拥抱多框架对比文档明确指出Kudu 选择不包含执行引擎但它支持足够的底层操作使外部执行引擎可以在节点本地node-local处理数据。这意味着Kudu 可以在同一份数据上支撑多种计算框架——例如 MapReduce、Spark 和 SQL——不同框架共享同一存储层。这与 Druid 形成鲜明对比Druid 的查询能力与存储深度耦合聚合、过滤都发生在 segment 内部换来的是针对 OLAP 的更优性能Kudu 则刻意保持存储与计算解耦换取跨框架的通用性代价是查询路径上少了存储层内置的优化。六、适用场景与选型建议综合对比文档的官方表述可以给出如下选型判断更适合选择 Apache Druid 的场景数据以事件流为主点击流、监控指标、日志聚合以追加写入为主、很少修改旧数据查询以OLAP 聚合、过滤、时间范围分析为主groupBy、TopN、时间序列数据量巨大希望通过摄入时 rollup 显著压缩存储、加速扫描希望获得开箱即用的位图索引与查询下推能力。更适合选择 Apache Kudu 的场景数据需要行级更新 / 删除或依赖任意主键的唯一性约束查询以主键范围查找为主而非按时间聚合同一份数据希望被MR、Spark、SQL 等多种框架共享处理不接受预聚合带来的明细丢失需要保留原始行。需要注意的取舍Druid 的40 倍压缩来自官方实践观测具体收益需结合自身数据的维度重复度与聚合粒度验证Druid 更新旧数据需要重建 segment见 更新已有数据属于高延迟操作若业务存在高频更新诉求Druid 并非理想选择Kudu 的更新机制需要预留额外存储空间且按 id 而非时间组织数据时间范围查询可能引入额外扫描成本两者并非严格互斥实践中可以在 Kudu 上做明细存储用 Druid 做聚合查询层各取所长。七、小结Apache Druid 与 Kudu 的差异本质上是OLAP 与 OLTP 设计哲学的较量Druid 以不可变 segment 时间分区 摄入时 rollup 位图索引 查询下推为代价换取聚合查询的高吞吐与低延迟Kudu 以行级更新 任意主键 存储与执行解耦为承诺换取更新友好与多框架通用。理解这一差异就能在事件数据的聚合分析与需要更新的明细存储之间做出清醒的选择——必要时两者也可以在同一数据流水线中互补共存。延伸阅读Druid vs 其他系统对比索引 同系列对比Druid vs SQL-on-Hadoop、Druid vs Elasticsearch、Druid vs Redshift 等Segments 设计文档segment 内部列式结构、位图与字典的实现细节批式数据摄入rollup 与granularitySpec的完整配置更新已有数据Druid 中重建 segment 更新旧数据的操作方式groupBy 查询文档Druid 聚合查询 DSL 详解IncrementalIndexSchema.javarollup 默认开启的源码证据IndexMerger.javasegment 合并与重建的实现BitmapIndex.java位图索引接口定义赞分享数据库数据分析OLAP大数据实时分析数据仓库后端【免费下载链接】druidApache Druid: a high performance real-time analytics database.项目地址https://gitcode.com/gh_mirrors/druid7/druid点击查看免费下载相关推荐Apache Druid 与 Kudu 对比面向实时 OLAP 的存储架构与查询模型差异解析Apache Druid 与 Kudu 对比面向实时 OLAP 的存储架构与查询模型差异解析 Apache Druid 与 Apache Kudu 都定位在大数据库OLAP大数据后端Loki DataObj 存储格式深度解析面向对象存储的列式日志容器格式Loki DataObj 存储格式深度解析面向对象存储的列式日志容器格式 DataObj 是 Loki 中用于在对象存储如 S3、GCS、OSS上读写结构可观测性日志分析后端微服务对象存储云原生DAOS面向未来的分布式异步对象存储DAOS面向未来的分布式异步对象存储 项目介绍 DAOSDistributed Asynchronous Object Storage 是一个开源的软件定创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表