news 2026/9/7 1:18:04

基于Apache Doris的供应链数仓平台建设实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于Apache Doris的供应链数仓平台建设实践

简介:这是一份2021年DataFunSummit峰会的演讲PDF,完整呈现蜀海供应链基于Apache Doris构建数仓平台的实践过程。面向大数据架构、数仓开发与数据分析岗位,可用于理解传统数仓改造为实时数仓的选型思路与落地方法。文档从业务场景切入,梳理了旧架构数据链路过长、聚合查询效率低、不支持标准SQL等痛点,再对比Doris的高并发查询、实时/离线导入、物化视图、在线Schema变更等特性,给出Canal监听Binlog、Kafka队列、Flink实时消费、Stream Load写入Doris的完整链路。还包含零代码入仓配置、元数据管理、Flink Doris Connector和收益表现,内容兼顾架构演进与实际踩坑。资料包共1个PDF,大小2.39MB,轻量易读;已有419人浏览学习,适合作为数仓平台建设方案的参考。

1. 经营数据散落四方,数仓要回答的最基础问题

2022年以前,我们团队在蜀海做数据工作,最常面对的一个场景是这样的:采购、仓储、配送、财务全部在用各自的系统,系统之间只通过单据流转。今天B端客户问一句"上周从下单到送达的平均时长是多少",我们发现要回答这个问题,需要把TMS的运单表、WMS的出库记录、订单系统的下单时间拼接在一起,再人工对账去重。整个链路下来,半天时间没了,而给出的数字,连我们自己都说不清误差有多大。

蜀海是餐饮供应链服务企业,业务涵盖从源头采购、中央厨房加工、冷链仓储、城市配送一直到门店端的全链路。这个行业有一个特点:链路很长,角色很多,每个环节都会产生数据,但每套系统的数据语言并不一致。例如,订单系统里那叫"客户",仓配系统叫"门店",财务系统里又变成"结算单位"。再加上生鲜领域特有的损耗折算、加权平均成本、差异化计量单位,数据口径的混乱程度完全超出了想象。

所以这个项目最初的动机非常朴素:不解决"数出多门、口径冲突、查询太慢"这三个问题,后续什么智能补货、需求预测、供应商绩效评估都是空话。说白了,先要把账算明白,才能谈用数据驱动业务。

当时我们盘了一下现状,数据源大概有ERP、WMS、TMS、订货平台、采购协同系统、财务系统六套核心系统,再加上一些Excel表格兜底。业务端的需求已经明显从"给我一张固定报表"转向了"我要随时自己组合维度看数据"。在这种背景下,需要选择一个合适的OLAP引擎来构建统一的数仓平台,把所有链条上的数据整合进来,建立一套让业务方能信服的口径和指标。于是就有了"基于Apache Doris的供应链数仓平台建设"这件事。

2. 选Apache Doris而不是ClickHouse或Presto,核心是"链路短、能Join、运维轻"

接触过OLAP选型的人都知道,市面上的引擎五花八门。我们做选型时,先列了核心诉求,然后逐条对照,结论其实比较清晰。

当时的候选主要是三个方向:ClickHouse、Presto+Hive数仓、Apache Doris。三者的架构哲学完全不同。

ClickHouse的强项是单表扫描极快,尤其是那种"一大张宽表、固定维度组合"的查询,性能非常惊艳。但它并不是为标准的星型模型多表Join设计的,一旦涉及大表Join大表,内存和SQL写法的限制会让开发同学很难受。而在供应链业务中,订单、明细、库存、批次天然是分表存储的,我们不可能为了让引擎跑得快,把所有维度都拍平到一张超宽表里,那会让建模失去弹性,开发效率也低。

Presto+Hive是更传统的湖仓方案:底层用Hive存数据,Presto做联邦查询。好处是生态成熟,能接各种数据源;坏处是架构重,组件多,查询引擎和存储引擎分离带来的网络开销在高峰期很明显。对我们这个体量的团队来说,维护一个Hadoop集群再维护一个Presto集群,人力成本不太划算。

Apache Doris最吸引我们的点总结起来有三条:MPP架构加上向量化执行引擎,单表和多表Join都能扛;兼容MySQL协议,开发人员基本零学习成本上手;内置存储和计算,不需要额外搭Hive和Spark做离线加工,数据导入直接通过Stream Load或 Routine Load 就能完成。用白话讲,Doris把"存储、计算、查询、导入"揉在了一个组件里,架构上的复杂度直线下降。

我还记得当时做了一次对比测试,用的是一张接近3亿行的订单明细表和一张60万行的门店维度表做Join聚合,Doris在并发8个查询的情况下,P95延迟稳定在1.2秒以内;同样的SQL放在ClickHouse上,性能波动很大,有时很快,有时因为内存不足直接报错。当然,这个结果和集群配置、表模型设计都有关系,不能一概而论,但从"开箱即用"和"团队能维护好"两个维度考虑,Doris在当时确实是综合得分最高的选择。后来我们实际跑了半年多,这个判断基本上也是站得住脚的。

3. 从ODS到ADS的四层建模,和供应链业务的对应关系

数仓建模没有银弹,关键是把业务过程拆清楚。我们在Doris上分了四层:ODS贴源层、DWD明细层、DWS汇总层、ADS应用层。这个结构不新鲜,但落地到供应链场景,每层做的事情是有行业特点的。

3.1 ODS层:先解决"数据语言统一"的问题

ODS层是数据的入口。我在这层踩过最大的坑是"只有新增没有变化"。业务系统的表往往是状态更新的,比如运单表里同一个运单号,仓库环节是"已出库",到了配送环节变成"配送中",最后一跳变成"已签收"。如果ODS层只做简单同步,每天拿的是一个覆盖后的快照,那数仓在做履历分析时就会丢失过程信息。

所以我们的做法是:对核心的订单、运单、库存流水表开启全生命周期保留,每天用分区存储全量快照;而对大流水的明细表按月分区增量同步。导入方式上,Doris的Stream Load帮了大忙,它支持从本地文件或HTTP接口以CSV、JSON格式批量导入,速度非常快,亿级文件基本在分钟级能完成。再加上Routine Load直接消费Kafka,实时接入门店要货、温控设备上报这类流式数据,ODS层的时效性做到了分钟级。

3.2 DWD层:事实表和维度表的"主数据攻坚战"

DWD层在供应链数仓里最大的难点不是SQL,而是主数据不一致。

举个具体例子:同一个商品,订货平台里编码是SPU00123,WMS里是SKU-456,到了财务系统又变成"精品五花肉-500g"这样的文本描述。如果不在DWD层做统一映射,后面的指标全部不可信。我们建了一张"商品主数据维度表",把上游六套系统的编码全部映射到统一的内部编码上,同时保留原编码字段,方便溯源。类似的工作还发生在供应商维度、门店维度。

在主数据基础上,DWD层落实的是事实表建模。我们构建了四类核心事实表:采购订单事实表、入库/出库流水事实表、库存快照事实表、配送履约事实表。这四张表几乎覆盖了供应链日常经营的全部核心流程。为了控制存储成本,维度字段做了编码化处理,文本字段长度比较克制,对高基数维度用Bitmap做精确去重,对低基数维度用字典编码。这个细节很关键:如果一张10亿行的明细表没做字段编码优化,光是文本冗余就能吃掉将近三倍的存储空间。

3.3 DWS层:按业务过程做"轻汇总"

DWS层是我个人最看重的一层。很多团队做数仓只做明细层,把明细层开放给下游随便查询,结果就是查询性能差,指标口径没法统一。我们的做法是,在DWS层按照业务过程建立轻汇总表,比如"门店日配达成汇总"、"仓内分拣效率日汇总"、"供应商到货准时率汇总"、"库存周转日趋势"。

这一层是Doris性能优势发挥得最充分的地方。因为DWS的数据量比DWD下降了一个到两个数量级,查询速度基本都在秒级以内。同时,业务方日常看的报表、管理层驾驶舱,绝大部分需求在DWS层就能满足。只有在少数需要溯源到明细的场景,才会下推到DWD层去查,这种分层策略既保障了性能,也把明细层的资源消耗控制住了。

3.4 ADS层:主题化输出,给不同角色定制数据产品

ADS层直接面向应用。我们按业务主题拆了多个应用数据集:采购分析、仓配分析、库存分析、销售分析、供应商绩效。每个主题内部其实就是一个或者一组物化视图或者逻辑视图,Doris的物化视图能力在这里很有用,它能自动维护预聚合结果,查询时可以直接命中,不需要额外做任务调度。

4. 数据服务层:数仓平台的API服务到底是个什么东西

这是后台不少人问过的问题,尤其当"数据服务"这个词出现在数仓平台的功能列表里时,很多人的第一反应是:数仓不是做报表的吗,API服务是什么?

4.1 业务背景:为什么不能让人直接连库查询

我们的数仓平台建设到中期,开始有越来越多外部系统接入的需求。比如供应商协同门户要查"对账单数据",门店App要查"当日配送进度",大屏系统要拉"实时库存总量"。如果让这些系统直接连Doris查库,且不说连接数限制、大查询互相争抢资源的问题,光是把Doris的账号密码暴露给那么多下游系统,安全风险就很头疼。

更麻烦的是,下游系统的调用逻辑五花八门,有人写SQL直接查表,有人要JSON接口,有人要键值对格式。如果每次都基于Doris裸表对接,那数据团队就成了纯苦力,任何一个字段改名都要层层通知。

4.2 API服务的实现方式:把数据查询能力封成接口

我们的解决方案是在Doris之上建了一层统一的数据服务层,把数据查询能力封装成标准RESTful API接口。核心逻辑很简单:你在数仓里算好结果表,然后在数据服务平台上配置一个接口,指定SQL模板、入参、出参格式、缓存策略、限流阈值,平台会自动生成一个HTTP接口。下游系统调用这个接口,拿到的是JSON数据,不需要关心底层数据存在哪个表。

举一个实际的例子:运营方需要"门店实时库存接口",入参是门店ID列表,出参是该门店在售商品的实时库存和可售天数。我们在DWS层的"门店库存快照汇总表"上配置了一个接口模板,SQL里写清楚"WHERE store_id = ?",然后通过数据服务平台的参数绑定机制动态执行。高峰期应用方每秒调用几十次,接口靠Doris的查询缓存兜底,P99延迟稳定在几百毫秒。

这个API服务本质上解决的是三件事:第一,权限控制——每个接口只暴露该暴露的数据字段,账号不出内网;第二,性能隔离——大查询和小查询在Doris侧通过资源组区分,接口调用不会被跑批任务拖死;第三,口径收敛——调用方拿到的是同一个SQL模板算出来的结果,不会再出现"A系统说库存1000、B系统说库存900"的扯皮。

4.3 构建数据API时的几个关键细节

如果你们也要在数仓平台上做数据服务API,我提几个比较重要的细节。

  • 参数查询一定要走预处理模板,不要直接拼SQL字符串,不然很容易产生安全问题。
  • 对高频接口加Redis缓存,TTL设置为30秒到5分钟之间,既能扛住突发流量,又不至于数据太旧。我们在"Doris查询 + Redis缓存"的组合下,把接口QPS从几十提升到几千,代价仅是数据延迟了几秒,业务完全可以接受。
  • 大结果集导出场景不要走同步接口,走异步任务:提交申请,后台跑完生成文件,再通过消息通知下载。
  • 每个接口要配超时时间和限流阈值。Doris本身很能扛,但不代表可以容忍下游滥用,一个没设限流的大查询就能把集群IO打满。

5. 硬核实测:数据量、查询性能、任务链路,以及踩过的坑

5.1 数据规模和最终的查询表现

上线半年后,整个平台沉淀了超过15亿行的明细数据,核心DWD表最大的订单明细事实表接近7亿行。在标准4节点集群配置下(每节点64GB内存、8核CPU、4块SSD),明细层单表扫描加聚合的查询基本都能在2秒到8秒之间完成,DWS层预聚合结果的查询则在百毫秒级。支持的最高并发是45个并发查询同时跑,系统整体没有出现明显的资源争抢。

这个成绩当然有运气成分,因为我们初期数据量还不算大,真正的挑战在后面的日增量持续增长。这带来一个直接建议:无论数据量多大,建表时一定要把分桶键和分区键设计对,它是后期所有查询性能的地基。

5.2 分桶键选错,Join性能掉了一个数量级

这是我们踩得最深的一个坑。最开始我们照着MySQL的习惯,把自增ID当作分桶键来建表,结果做多表Join时,因为Join字段和分桶键不一致,Doris需要把两边的数据做全量的Shuffle重分布,3亿行的订单表和60万行的门店表Join,跑了将近40秒才出结果。

后来我们把常用维度表的Join字段(门店ID、供应商ID、商品ID)作为Doris表的分桶键,并把分桶数按照数据总量做了合理规划。同样的查询,从40秒优化到了3秒以内。

所以我的建议是:建表前先想清楚常用的查询过滤字段和Join字段,优先把组合键作为分桶键。分桶数量的设置也很有讲究,一般在"每个桶的数据量控制在300MB到1GB之间"比较合理。

5.3 大批量历史数据的更新:Unique模型和Delete标记的取舍

我们有大量的"补录"和"修正"场景。比如某个门店发现上个月的配送记录漏掉了,需要重新补单。在Doris的Unique Key模型里,如果直接UPDATE这几行,会产生新的版本文件,旧文件不会立刻被清理,时间长了会导致版本文件堆积,查询变慢。

后来我们的策略是:对于大批量历史数据修正,不直接做UPDATE,而是用"删掉该业务日期分区 + 重新INSERT该分区的新数据"的方式。这个操作在Doris里是一套事务流程,先DELETE分区,再LOAD新数据,能避免版本文件碎片化。实践下来效果很好,查询性能没有因为历史修正产生明显回退。

5.4 BE节点内存和Compaction的日常监控

作为运维侧的经验,我要多说一句:Doris虽然运维相对简单,但日常监控不可省。重点盯两个指标:BE节点的内存使用率,以及Compaction的积压任务数。

我们线上曾经出现过一次Compaction积压,原因是某个大表的导入过于频繁,小文件数激增,BE节点忙于合并版本文件,查询性能直接腰斩。解决办法是控制导入频率,把高频小批次导入改成定时大批次导入,配合Doris的Compaction策略手动触发一次。从那以后,我们团队定了一个规矩:任何大表的导入任务,先评估单表文件数,超过阈值就做合并,避免"小文件风暴"。

5.5 查询队列和资源组:防止"一颗老鼠屎坏一锅粥"

最后讲一个长期受益的配置。日常跑批任务和线上用户即席查询混在一起,一旦有人按错了全表扫描,会把集群IO瞬间打满,其他人全部拖慢。Doris的资源组隔离和查询队列在这里非常好用。我们把跑批任务放在一个独立的资源组,对CPU、内存、IO做上限控制;即席查询放在另一个资源组,并且设置了查询超时和内存限制。这样一来,跑批再重也不会阻塞前台看板,偶尔有奇葩大查询也会被资源组拦截住,不会殃及所有人。

6. 这个架构能用多久,以及给同行的一点参考

回到最初的问题:基于Apache Doris的供应链数仓平台,是不是一套可以长期依赖的架构?我的判断是,在蜀海当前的业务体量下,这套架构至少能支撑未来两到三年的数据需求。理由很简单:Doris的线性扩展能力可以通过增加BE节点实现,不需要停机,数据重分布自动完成,这对业务快速变化的供应链场景非常友好。

如果哪一天数据量真的到了几百亿行,我们也可以考虑引入分层存储,把冷数据放到对象存储,Doris本身对冷热分层有原生支持,这个演进路径也是通的。

对同行来说,如果你们也是典型的供应链企业,业务链路长、数据源多、查询需求变化快、团队规模又不算大,Doris这条路线是值得认真评估的。在选型前,我建议你们先花两周时间把核心的十张表真实数据导入Doris,跑几个真实业务查询,重点看Join性能、导入耗时、以及高并发下的稳定性。数据永远比PPT上的理论更有说服力。

最后分享一个我在整个项目中最深的体会:数仓平台的建设,技术上选型固然重要,但真正决定成败的,是你在ODS层和DWD层处理主数据、统一口径时下的笨功夫。那些看似枯燥的编码映射、字段清洗、历史数据订正,才是业务方能真正信赖你输出的每一个指标的根本原因。如果基础打得牢,Doris的查询能力就像锦上添花;如果基础不牢,再强的引擎也救不了混乱的逻辑。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 1:17:29

中国到英国物流专线怎么选才不踩坑?

盛林英国物流专线怎么样?一文说清时效、费用与适用人群核心结论盛林英国物流专线是盛林国际物流(盛林物流)旗下覆盖中国至英国的海运、空运专线服务,主打门到门、双清包税的一站式运输,适合有FBA送仓或大宗贸易发货需求的跨境电商卖家与外贸企业。 该结论成立的前提是:货物属于…

作者头像 李华
网站建设 2026/9/7 1:17:22

欧洲物流专线怎么选才不踩坑?一份按需求决策的选购指南

结论摘要:先给你直接答案欧洲物流专线没有"唯一靠谱"的答案,"靠谱"与否取决于你的货物类型、时效要求、预算和合规需求是否匹配。把问题拆成三步判断,基本就能锁定方向:看货:你的货是普货还是超大件、敏感货?特殊货物直接淘汰掉一半以上线路。看交付方式:…

作者头像 李华
网站建设 2026/9/7 1:17:18

ANSYS CFX理论指南:从求解器原理到收敛排查实战

简介:《ANSYS CFX-Solver Theory Guide》是ANSYS官方发布的CFX 19.0求解器理论指南,面向从事计算流体动力学(CFD)的工程师、科研人员及高年级学生,系统阐述有限体积法求解框架、控制方程离散化、边界条件设置、湍流模型…

作者头像 李华
网站建设 2026/9/7 1:17:12

基于SpringBoot的普洱茶文化科普与销售系统(源码+lw+部署文档+讲解等)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

作者头像 李华
网站建设 2026/9/7 1:15:11

DHT11单总线协议深度解析:时序、驱动实现与踩坑指南

很多人第一次接触DHT11,都会觉得这玩意儿太简单了:便宜、四根引脚、网上例程一抓一大把。真到自己上手做项目,才发现照着抄的代码就是读不出数据,不是显示湿度255%,就是温度乱跳,更有甚者直接卡死在读取函数…

作者头像 李华
网站建设 2026/9/7 1:14:55

无sudo权限部署RIOT网络工具:用户态环境变量实现28Mbit/s吞吐

1. 事情起因:一台“锁死”的 Ubuntu 机器先说下我手头的处境,你可能也遇到过。公司在用的 Ubuntu 22.04 LTS 工作站,账户是普通用户,sudo 密码没给我,系统里的依赖也基本不敢乱动——怕影响其他人用。你懂的&#xff0…

作者头像 李华