news 2026/9/25 7:33:57

Apache Doris深度解析:架构原理、数据模型与部署实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Apache Doris深度解析:架构原理、数据模型与部署实战指南

做数据平台的同学,这两年应该没少听说 Doris。不管是实时数仓、大数据分析,还是 BI 报表加速,Doris 几乎都会出现在候选名单里。我第一次在一个几十亿行明细的网约车订单场景里跑 Doris 时,说实话是被它的查询速度吓了一跳的——一个需要聚合多维指标、原来在 Hive 上要跑二十多分钟的任务,切到 Doris 之后秒级返回。这篇文章不打算写官方文档翻译,而是从大数据从业者的视角,把 Doris 的核心特性、架构设计、部署实战和坑位都过一遍,帮助正在做技术选型或者准备入手 Doris 的同学快速判断它适不适合自己的场景。

Doris 真正的价值不在于单点性能有多夸张,而在于它把“离线批量分析”和“实时交互查询”揉进了同一个系统里。你不需要再维护一套复杂的 Lambda 架构,不需要在 HBase、ES、Presto、ClickHouse 之间来回兜圈子,一张表既能接实时流,又能批量导历史数据,查询还不需要提前预聚合。这种“一个引擎打天下”的思路,在大数据工程里是很奢侈的,但 Doris 确实做到了。下面我从原理讲到实战,把重点都拆开说清楚。

1. 先盘清楚:Doris 解决的是大数据分析里的哪些问题

1.1 大数据架构里的典型痛点

传统的大数据分析链路,很多团队是这么搭的:Kafka 接日志,Flink 做实时 ETL,结果落到 HBase 或者 ES 里供实时查询;历史数据进 Hive,定时跑 Spark 任务出报表;再挂一个 Presto 或者 Impala 做交互式查询。这套架构本身没什么问题,但维护成本很高,而且链路一旦长了,数据口径容易对不上。

我见过太多团队,实时链路和离线链路各做一套数仓,同一个“订单金额”指标,实时算出来是 100 万,离线算出来是 98 万,两边业务方天天扯皮。根源就在于实时数据和离线数据分别存在不同的存储引擎里,查询引擎也不一样,很难做到一份数据、统一口径。还有一个更直接的痛点:明细查询慢。业务方经常要看某一天某个用户的所有行为明细,这种点查在 Hive 上就是灾难,在 HBase 上又要提前设计 RowKey,灵活性极差。

Doris 一开始就是冲着这些问题设计的。它的定位是 MPP(大规模并行处理)分析型数据库,既有 ClickHouse 那种列式存储的查询性能,又有 Presto 那种灵活做复杂 Join 的能力,还提供了类似 Greenplum 的分布式事务能力。对大数据工程师来说,它最大意义在于把实时和离线两条链路合并成了一条,查询引擎、存储引擎、数据模型完全是同一套,不再有口径割裂的问题。

1.2 Doris 的定位:一个 MPP 分析型数据库

Doris 的架构核心是两个角色:FE(Frontend)和 BE(Backend)。FE 负责元数据管理、SQL 解析、生成执行计划、查询调度,类似于一个“指挥官”;BE 负责数据存储和查询计算,类似于“一线工人”。FE 和 BE 都可以水平扩展,节点挂掉之后有自动故障转移机制,不需要额外依赖 ZooKeeper 之类的第三方组件。

从使用感受上说,Doris 更像是“分布式 MySQL + ClickHouse 的结合体”。它兼容 MySQL 协议,你写 SQL 的习惯可以完全保留,直接用 Navicat、DBeaver 这类 MySQL 客户端就能连上去。但底层存储又完全是列式存储加 MPP 并行处理,所以分析型查询的性能远远超过普通 MySQL。很多团队从 MySQL 迁移到 Doris 之后,报表接口的耗时直接从几秒降到了几十毫秒,体感非常明显。

1.3 为什么是 Doris,而不是其他 OLAP 引擎

每和一个团队聊 Doris,都会有人问:为什么不用 ClickHouse?为什么不用 StarRocks?为什么不用 Greenplum?我的看法是:选 Doris 不是因为别的引擎不行,而是 Doris 在“易用性”和“功能完整性”之间找到了一个很舒服的平衡点。

ClickHouse 的单表查询确实极快,但多表 Join 支持得不好,并发能力也比较弱,更适合做单表大宽表的分析。Presto 的交互查询很强,但它没有自己的存储层,底层还是要靠 Hive 或者对象存储,做不到实时写入。Doris 自己管存储、自己管计算、自己管事务,还支持标准的 Join、子查询、窗口函数,这一点在开源 OLAP 引擎里非常有优势。再加上 Doris 已经捐给了 Apache 软件基金会,社区活跃度稳定,版本迭代也快,企业用起来放心。

2. 核心技术拆解:为什么它快得不像传统数仓

2.1 MPP 并行计算框架

MPP 架构是 Doris 高性能的基础。一个查询发到 FE 之后,FE 会把它拆成多个执行计划片段,分发到不同的 BE 节点上并行执行。每个 BE 只处理自己本地的那部分数据,最后再汇总结果。因为数据就在本地,扫描过程不需要把全量数据拉到一台机器上,网络开销被压到了最低。

对比一下 Hive 的 MapReduce 模型就明白了。Hive 跑一个聚合任务,要经历 Map 阶段、Shuffle 阶段、Reduce 阶段,中间还有大量落盘,每一层都有网络和磁盘 IO。Doris 的 MPP 引擎把所有计算尽量下推到数据所在的节点,扫描完直接做部分聚合,只有中间结果才需要传输。这个策略让 Doris 在几十亿行数据的聚合场景下,依然能做到秒级返回。

2.2 列式存储、前缀索引与数据裁剪

Doris 底层是列式存储,每列单独存文件。分析型 SQL 往往只需要读少数几个字段,列式存储天然就能做到“要什么读什么”。举一个我实际见过的例子:一张订单表有 80 个字段,每天新增 2000 万行,业务方只查“城市、订单量、GMV”三个维度。列式存储只需要读取这三个列的文件,I/O 量比行式存储少了十倍不止,查询能不快的道理就在这。

Doris 每个表可以指定 Key 列,数据会按照 Key 列的顺序排序后存储。它给这层排序做了一个类似“目录”的前缀索引(Short Key Index),查询时如果条件命中了前缀列,就能直接跳过大量无关数据块。再加上每个数据块都会记录最大值、最小值的 ZoneMap 索引,以及可选的 BloomFilter 索引,三层索引下来,扫描的数据量会被裁剪得极少。很多人低估了 Doris 的索引能力,实际上在大数据量下,真正读出来的数据往往只有总量的百分之几。

2.3 向量化执行引擎:从逐行到批量

Doris 从 1.1 版本开始默认启用向量化执行引擎,这是一个质变。传统数据库执行 SQL 是一行一行地处理,每行都要经历函数调用、类型判断、分支跳转,CPU 浪费很大。向量化引擎的思路是一次处理一批数据(比如 4096 行),利用 CPU 的 SIMD 指令做批量计算,让内存带宽和 CPU 流水线都充分利用起来。

打个比方,传统执行方式就像快递员按个派件,一次拿一件跑一趟;向量化执行就像把几百个包裹一次性装车,再沿着小区一路投放。处理单行数据的开销被平摊到了上百行里,整体吞吐自然大幅提升。SSB 测试里 Doris 的查询性能可以跑到传统数仓引擎的几倍到十几倍,和这个向量化设计有直接关系。

2.4 CBO 优化器的实际价值

Doris 内置了基于代价的优化器(CBO,Cost-Based Optimizer)。它会收集表的统计信息,包括行数、数据大小、列基数等,然后估算不同执行路径的代价,自动决定最优的 Join 顺序、是否做谓词下推、是否选择 Colocate Join 等。

这个能力在复杂查询里特别关键。比如一张大表同时 Join 三张小表,Join 顺序不同,中间结果量差出几个数量级。CBO 能自动把小表作为驱动表,控制中间结果膨胀。我们内部有些 SQL 是直接从 Hive 迁移过来的,在一个多表 Join 的场景里,Doris 的优化器跑出来的执行计划比我们自己手工调优的还要稳。对使用者来说,这减少了大量手动调优成本。

3. 核心特性与业务优势:不止是快

3.1 实时与离线分析一体化

Doris 支持多种数据导入方式:Stream Load 适合小批量实时写入,Routine Load 可以直接订阅 Kafka 数据流做准实时导入,Broker Load 适合大批量从 HDFS、对象存储导入历史数据,Flink Doris Connector 则让实时计算链路无缝衔接。最妙的是,无论数据通过哪种方式写入,查询接口完全一致。

我们在实际项目中是把日志数据从 Kafka 通过 Routine Load 直接进 Doris,同时每天凌晨用 Broker Load 把前一天的历史分区数据补进同一张表。业务方看到的永远是一张完整的表,既查得到最近几秒的数据,也能查历史 180 天的数据。这个能力直接省掉了一套 HBase 实时链路,也省掉了“实时结果对不上离线结果”的争论。

3.2 高并发点查能力

很多 OLAP 引擎的单查询性能不错,一上并发就崩。Doris 在高并发场景的表现在 MPP 引擎里是很能打的,原因在于它的本地索引和数据分区分桶设计。点查只要命中 Key 列,查询可以直接定位到少数几个 Tablet,不需要全表扫描。

在线服务场景也可以用它,比如用户详情的多维查询、订单明细查询、标签命中查询。我们之前有个接口,QPS 要求 500,P99 延迟要求 300 毫秒以内,用 Doris 做存储后顺利过了压测。但要强调一点,Doris 是分析型数据库,不是 OLTP 数据库,它不适合做高频事务更新,单条数据更新也不是它的强项。把它放到“分析服务”的位置上,它会表现得很亮眼。

3.3 三种数据模型到底怎么选

Doris 提供了三种表模型,选错模型是很多新手最常见的坑。

Duplicate 模型适合明细数据,比如日志、行为流水,不去重、不更新,每行都会保留。Aggregate 模型会在导入时预聚合,比如把点击量按天、按用户预先 SUM 好,这样查询时数据量已经小了很多,速度会再上一个档次。但它有一个限制,只能查询预聚合的列。Unique 模型适合订单、用户档案等有更新需求的场景,主键相同的新数据会覆盖旧数据,保证数据唯一性。

举一个网约车场景的例子:订单明细表用 Duplicate 模型保存原始流水;订单聚合统计表用 Aggregate 模型按天、城市、司机聚合订单数和金额;订单状态是动态变更的,比如从“进行中”改到“已完成”,这种就要用 Unique 模型。实际建表前,先想清楚业务是“只进不出”“只查汇总”还是“频繁更新”,再定模型,能少走很多弯路。

3.4 周边生态和兼容性

Doris 的生态整合能力,在开源 OLAP 引擎里算做得比较完整的。对外兼容 MySQL 协议,几乎所有 BI 工具都能直接接入;对内提供了 Hive Catalog、Iceberg Catalog、Hudi Catalog,可以直接做联邦查询,不用把数据复制进来也能关联分析。Flink 连接器是官方维护的,支持 Exactly-Once 语义,Spark 读 Doris 也很方便。

有人会纠结 Doris 和 Hive 的关系。我的看法是:Hive 更适合做离线数仓的底层存储和 ETL 计算层,Doris 更适合做服务层和加速层。以校园大数据项目为例,可以用 Spark/Hive 做数据清洗和宽表计算,结果落到 Doris,再用 Flask + ECharts 做可视化展示,Doris 在里面承担的就是“数据服务中枢”的角色。清洗和计算交给数据湖生态,展示和查询交给 Doris,各干各擅长的事,配合起来效率最高。

4. 落地实战:从集群部署到查询优化

4.1 集群规划与部署步骤

Doris 部署极简,三台机器起步就能搭一个高可用集群。机器规格上,建议每一台至少 16 核 64G 内存,磁盘用 SSD,BE 节点数建议 3 个以上。FE 节点可以单独部署,也可以跟 BE 混合部署,小规模集群混合部署没问题,但生产环境建议 FE 独立节点,避免 BE 的内存抖动影响 FE 的稳定性。

部署步骤我一般这么走:

  1. 从 Doris 官网下载对应版本的二进制发行包,解压到/opt/doris。
  2. 配置 FE:修改fe/conf/fe.conf,重点设置priority_networks,因为多网卡机器如果不指定网段,FE 会取错 IP 导致节点无法通信。
  3. 启动 FE:执行sh bin/start_fe.sh --daemon,然后通过mysql -h127.0.0.1 -P9030 -uroot登录验证。
  4. 配置 BE:修改be/conf/be.conf,同样设置priority_networks,然后执行sh bin/start_be.sh --daemon。
  5. 在 FE 上执行ALTER SYSTEM ADD BACKEND "be_ip:9050";,再用SHOW BACKENDS看状态是否变为Alive。

第一次部署常见的坑就是priority_networks没配好,FE 一直显示 BE 是 Dead 状态。检查这个配置的第一个位置,而不是去查什么复杂的原因。另外 FE 的 JVM 内存默认是 8G,如果小机器内存紧张,记得在fe.conf里调小JAVA_OPTS,否则集群可能因为内存不足频繁告警。

4.2 建表与查询调优的几条实战经验

建表的时候,分区和分桶策略直接影响查询性能。我常用的经验是:按日期做分区,按高频等值过滤字段(比如用户 ID、城市 ID)做分桶。分桶数不宜过小也不宜过大,每个桶的数据量控制在 1GB 左右是实践经验。一个常见错误是拿低基数字段分桶,比如按“省份”分桶,全省的数据都压到同一个桶里,并行度根本提不上来。

Key 列的顺序也很重要。前缀索引只对 Key 列的最前面几个字段生效,所以要把最常用于过滤的字段排在前面。比如订单场景,顺序应该是订单日期、城市、用户 ID,这样“查某一天某城市的所有订单”会被前缀索引直接优化。如果 Key 列顺序反了,索引就失效,查询全表扫描,性能天差地别。

Join 优化方面,Doris 支持 Colocate Join——如果两张表的分桶方式和分桶数完全一致,Join 可以在本地完成,不需要跨节点传输数据。把多张常用关联的大表设计成相同分桶规则,收益非常明显。另外小表 Join 大表时,Doris 会自动做广播,把小表复制到各节点,这种场景不用手工干预都很稳。高基数聚合时,建议近似去重函数BITMAP或HLL,误差很小但内存开销能降一个数量级,用来算 UV 这种指标非常合适。

4.3 我在实际项目中踩过的坑

没有哪个数据库能免于踩坑,Doris 也一样。把我遇到最多的问题整理成表格,给大家做一个速查:

问题现象常见原因排查思路
BE 节点状态一直 Dead网络不通、priority_networks配置错误检查网络和端口 9050、8040 是否通,查看 BE 日志
导入时报 “Too many open files”系统文件句柄限制太低调大ulimit -n,BE 需要至少 65536
查询报 “Memory limit exceeded”BE 内存不足或查询过大调mem_limit,优化 SQL 减少数据扫描量
Tablet 副本数异常告警副本数设置不合理,或磁盘空间不均衡分桶数重新规划,关注集群的磁盘均衡状态

最隐蔽的一个坑是:用 Aggregate 模型建表后,查询里对 Value 字段既没有求和也没做聚合,直接SELECT原生值,结果查出来是一堆没有意义的中间状态数据。Aggregate 模型不是普通的明细表,Value 列必须用聚合函数访问,建表时要想清楚查询场景,否则数据都堆进去了但查出来的结果完全对不上。

4.4 典型大数据场景怎么用它

校园大数据方向的案例里,Doris 经常被当作“数据可视化服务端”。前面用 Python 或 Spark 做数据清洗,把清洗后的数据导入 Doris,再用 Flask 提供 API,ECharts 画大屏。Doris 在这类项目中最大的好处是:建立一张汇总表之后,即使数据量到了百万级,按院系、年级、课程维度做统计,前端接口响应依然很快,不会出现图表转半天才出来一个圈的情况。

网约车大数据项目是我觉得最贴近 Doris 真实业务形态的场景。订单流水实时进 Doris,司机绩效、城市热力、时长分布这类指标直接在 Doris 里跑实时查询;历史数据按天分区归档,离线分析直接查同一张表。整个项目用 Spark 做清洗、Doris 做分析和存储、Flask + ECharts 做可视化,一条链路串下来,架构清爽,每个模块的分工也足够清晰,非常适合作为数据相关项目的技术骨架。

5. 常见问题速查与排障思路实录

5.1 客户端连接和数据导入问题

连接 Doris 失败,优先级最高的检查点有两个:一是 FE 的查询端口 9030 是否开放,二是用户名和密码是否匹配。如果使用 MySQL 客户端连 Doris,有时会报认证插件不支持的错,需要在客户端加--default-auth=mysql_native_password参数。这些细节不起眼,但在跨版本迭代的时候特别容易碰到。

数据导入是新手最容易踩雷的环节。Stream Load 导入如果报Label Already Exists,说明上一次导入任务的标签还在事务里,用SHOW LOAD查看该 Label 状态并清理后再重试。Routine Load 订阅 Kafka 时,如果报 offset 越界,大概率是 Kafka 的清理策略把旧消息清掉了,而 Doris 记录了旧的 offset,重置消费位点后一般能解决。养成“导入任务都要设置 Label”的好习惯,排查问题的时候会方便非常多。

5.2 一些 SQL 执行与性能问题的排查经验

一个典型的慢查询场景:SQL 没建好前缀索引,导致全分区扫描。排查的时候可以先看EXPLAIN输出,确认实际扫描分区数。如果显示所有分区都扫了,就要考虑调整过滤条件或表设计。Doris 的EXPLAIN非常好用,能把每个算子的行数和耗时都展示出来,大多数性能问题在执行计划里就能看出来端倪。

另一个常见问题是 Join 时内存被打爆。两张超大表做 Join,如果没有任何等值关联条件,会产生笛卡尔积,这是绝对要避免的。即使有等值条件,数据倾斜也容易导致某个 BE 节点内存暴涨。遇到这种情况,先看倾斜 Key 能不能通过加随机数打散,再考虑是否用 Broadcast 或 Colocate Join 来规避。还有一点要注意,LIMIT N语句里 N 很大时需要排序,排序量过大会占内存,尽量在 SQL 里用时间分区先把数据范围缩小。

5.3 与周边组件配合时的常见注意点

通过 Presto 连接 Doris 做联邦查询时,我遇到过类似 “Column missing” 的报错,排查到最后发现是列名大小写不匹配。Doris 的表结构如果定义了大小写混合的列名,Presto 端未加引号的标识符会被统一转成小写,两边元数据对不上,自然就报 missing。解决办法很简单:建表统一用小写列名,或者查询时把列名用双引号包起来。另一个容易踩的坑是 Hive Catalog 同步表结构之后,Hive 那边改了 schema 但 Doris 的元数据缓存还没刷新,需要执行REFRESH CATALOG刷新一下。

Flink 实时写入 Doris 时,如果任务并行度过高,且 BE 节点的小文件过多,会造成导入性能下降。官方连接器一般建议并行度不要超过 BE 节点数量的三倍。Spark 批量导入时,如果单线程写太慢,可以用 Broker Load 配合多副本并行,吞吐能提升好几倍。和周边组件配合时,先把边界职责搞清楚,再考虑调优,否则定位问题会非常费劲。

6. 学习路径建议:按这个顺序少走弯路

6.1 基础准备

入门 Doris 之前,最好有一些 SQL 基础,理解分组聚合、多表关联、窗口函数这些概念。大数据的整体知识最好也有一点,至少要知道 HDFS、Hive 和实时数仓是干嘛的。你可以没有二十年大数据经验,但得清楚 Doris 在整个链路里处于“查询服务层”这个位置,这样学起来才有坐标系。

如果身边没有现成集群,用单机版 Doris 就够了。官网有 Quick Start 文档,下载二进制包,配置好 FE 和 BE,导入官方示例数据,跑几个查询,核心体验基本就到位了。单机部署和集群部署的差异没有那么大,先把一套跑通,再扩展节点也来得及。

6.2 一套实操学习路线

第一步,理解 Doris 的 FE / BE 架构和数据模型,把 Duplicate、Aggregate、Unique 三种模型的区别用自己的话讲清楚。第二步,跟着官方文档完成部署,建一张订单表,用 Stream Load 和 Broker Load 两种方式导入数据,跑常见聚合查询。第三步,学习 Routine Load 接入 Kafka,尝试做一张实时更新的汇总表。第四步,开始看执行计划,对着慢查询做优化,把分区分桶、Key 列顺序、Colocate Join 这些概念一一验证一遍。第五步,接一个可视化工具,把查询结果展示出来,形成完整闭环。

这套路线走完,基本能应付大部分生产环境的使用场景了。之后如果碰到大数据 SQL 面试相关的问题,Doris 大概率会被问到:它和 Hive 有什么区别、和 ClickHouse 有什么区别、在什么场景下选它。这些问题的答案其实都在上面的实践里,不是靠背下来的,而是跑过之后自然就能说出来。

6.3 资源推荐

官方文档永远是第一手资料,部署配置、SQL 语法、导入导出都有很详细的说明。Doris 官方公众号和社区论坛也经常发布版本预告和性能调优案例,值得长期关注。如果你想系统性学习,可以看看 Doris 官网上的最佳实践栏目,里面有各大厂公开的架构演进和调优文章,参考价值很高。

我个人实际操作下来的体会是:Doris 的学习曲线在同类 OLAP 引擎里属于很平缓的,基本照着官方文档走一遍就能上手,真正难的是把表模型选对、把分区分桶设计好。还有一个小技巧想分享给正在做选型的人:不管网上评测怎么说,都先拿一份自己业务最复杂的 SQL,部署一个测试环境导入小批量数据对比一下,用真实查询验证,比看任何 PPT 都靠谱。Doris 到底适不适合你的场景,跑一次就知道了。

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

HC32L13x Keil编译报错__WEAK undefined:根因排查与中断函数正确写法

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 7:32:20

一文读懂I2C、SPI、I2S、UART:串行通信选型与时序分析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/25 7:30:16

部署和发布PHP网站到IIS服务器的全过程

稳定版本博主当前时间最新稳定版本是Current Stable PHP 8.3.13,点击Windows downloads即可线程安全版在跳转页面,建议选择VS16 x64 Thread Safe(线程安全版本,以及直接是Zip压缩包,下载后,直接解压复制文件…

作者头像 李华
网站建设 2026/9/25 7:29:57

vim全选、全部复制、全部删除:模式与寄存器核心操作详解

刚接触Linux的人,十有八九会在vim里卡住。图形编辑器里CtrlA全选、CtrlC复制、CtrlD删除,一套肌肉记忆带进终端,结果vim愣是没反应。这个场景我见过太多次:有人以为vim坏了,有人干脆放弃,还有人直接在终端里…

作者头像 李华
网站建设 2026/9/25 7:28:35

OCS网课助手题库API配置全攻略:从原理到实战提升答题正确率

1. 从“手动刷课”到“自动答题”:OCS网课助手到底在解决什么问题如果你正在看这篇文章,大概率是手里已经装了 OCS 网课助手,或者正准备装,卡在了“题库 API 怎么配”这一步。先说结论:OCS 本身只是一个“壳”&#xf…

作者头像 李华