Apache Doris 学习文档(面向开发人员)

Apache Doris 学习文档(面向开发人员)

Doris 是什么?为什么你需要它?

数据库类型 典型代表 特点 适用场景
OLTP(事务型) MySQL, PostgreSQL 强一致性、高并发写、行存 订单、用户信息等业务系统
OLAP(分析型) Apache Doris, ClickHouse, StarRocks 高吞吐查询、列存、MPP 架构 报表、BI、日志分析、用户行为分析

Apache Doris 是一个开源的、高性能、实时的 MPP 分析型数据库,采用列式存储,兼容 MySQL 协议,专为 OLAP(在线分析处理) 场景设计。

为什么你需要它?

✅ 快:TB 级数据秒级查询(聚合、多维分析)

✅ 实时:支持 Kafka/HTTP 秒级写入,数据即时可见

✅ 简单:无 Hadoop 依赖,部署运维轻量

✅ 易用:标准 SQL + BI 工具直连(如 Tableau、Superset)

✅ 省成本:开源免费,高压缩比降低存储开销

🎯 适用场景:实时数仓、日志分析、BI 报表、用户行为分析。

❌ 不适用:高频点查、强事务、全文检索(这类需求选 MySQL 或 Elasticsearch)。


Apache Doris 整体架构图

graph TD subgraph "客户端层" A[MySQL Client] -->|SQL| B(FE) C[JDBC/MyBatis] -->|SQL| B D[Stream Load] -->|HTTP| B E[Routine Load] -->|Kafka| B end subgraph "计算与协调层 (FE - Frontend)" B --> B1[SQL Parser] B --> B2[Planner] B --> B3[Scheduler] B --> B4[Metadata Manager] B4 -->|持久化| B5[(BDBJE
doris-meta/)] end subgraph "存储与执行层 (BE - Backend)" B --> F[BE Node 1] B --> G[BE Node 2] B --> H[BE Node N] F --> F1[Tablet 1] F --> F2[Tablet 2] F --> F3[Storage Engine] F3 --> F4[(Data Files
storage_root_path/)] G --> G1[Tablet 3] G --> G2[Tablet 4] G --> G3[Storage Engine] G3 --> G4[(Data Files)] H --> H1[...] H --> H2[Storage Engine] H2 --> H3[(Data Files)] end subgraph "数据源" I[Kafka] -->|Routine Load| B J[Local File] -->|Stream Load| B K[HDFS/S3] -->|Broker Load| B end classDef fe fill:#4CAF50,stroke:#388E3C,color:white; classDef be fill:#2196F3,stroke:#0D47A1,color:white; classDef storage fill:#FFC107,stroke:#FF8F00; classDef client fill:#9E9E9E,stroke:#616161,color:white; class B,B1,B2,B3,B4,B5 fe; class F,G,H,F3,G3,H2 be; class F4,G4,H3 storage; class A,C,D,E,I,J,K client;
只需记住两个角色:
组件 作用 类比理解 是否需要你关心?
FE (Frontend) 接收 SQL、管理元数据、调度查询 ≈ MySQL Server 层 ❌(部署好就不用管)
BE (Backend) 真正存数据 + 执行计算 ≈ InnoDB + 分布式计算引擎 ✅(扩容加 BE 节点即可)

💡 关键特点:

  • FE 无状态:可多节点部署,自动选主

  • BE 自动均衡:加机器后数据自动分片

  • 你只用连 FE:像连 MySQL 一样简单


Doris 核心能力(开发者最关心的)

常用写入方式

Broker Load(推荐用于大文件批量导入)
  • 原理:通过 Doris 内置的 Broker 进程(如 HDFS、S3、OSS、BOS 等)从外部存储系统并行拉取数据。

  • 支持格式:CSV、Parquet、ORC

  • 特点:

    • 异步导入,适合 GB~TB 级大文件

    • 自动分片、并行处理

    • 支持断点续传(部分失败可重试)

  • 适用场景:

    • 从 HDFS/S3 导入历史数据

    • 每天一次的 T+1 批量同步

  • 示例:

sql 复制代码
LOAD LABEL broker_load_2022_04_01
(
    DATA INFILE("s3://your_bucket_name/brokerload_example.csv")
    INTO TABLE test_brokerload
    COLUMNS TERMINATED BY ","
    FORMAT AS "CSV"
    (user_id, name, age)
)
WITH S3
(
    "provider" = "S3",
    "AWS_ENDPOINT" = "s3.us-west-2.amazonaws.com",
    "AWS_ACCESS_KEY" = "<your-ak>",
    "AWS_SECRET_KEY"="<your-sk>",
    "AWS_REGION" = "us-west-2",
    "compress_type" = "PLAIN"
)
PROPERTIES
(
    "timeout" = "3600"
);

Stream Load(推荐用于实时/小批量 HTTP 推送)
  • 原理:通过 HTTP 协议将本地文件或内存数据直接推送到 Doris。

  • 支持格式:CSV、JSON(支持多行 JSON)

  • 特点:

    • 同步返回结果(成功/失败)

    • 低延迟(秒级可见)

    • 支持 实时流式写入

    • 可通过 Nginx 负载均衡到多个 BE 节点

  • 适用场景:

    • 日志采集(Filebeat → Stream Load)

    • Flink/Spark 实时写入

    • 应用程序直接推送数据

  • 示例(curl):

http 复制代码
curl --location-trusted -u <doris_user>:<doris_password> \
    -H "label:124" \
    -H "Expect:100-continue" \
    -H "format:json" -H "strip_outer_array:true" \
    -H "jsonpaths:[\"$.userid\", \"$.username\", \"$.userage\"]" \
    -H "columns:user_id,name,age" \
    -T streamload_example.json \
    -XPUT http://<fe_ip>:<fe_http_port>/api/testdb/test_streamload/_stream_load
Routine Load(推荐用于 Kafka 实时持续消费)
  • 原理:Doris 自动创建后台任务,持续从 Kafka 消费数据并导入。

  • 支持格式:CSV、JSON

  • 特点:

    • 自动容错:Kafka offset 自动管理,失败自动重试

    • Exactly-Once 语义(通过 label 去重)

    • 支持 Kafka 多分区并行消费

  • 适用场景:

    • 实时数仓(Kafka → Doris)

    • 用户行为日志、交易流水实时入库

  • 示例:

sql 复制代码
SHOW ROUTINE LOAD FOR tbl_name;

CREATE ROUTINE LOAD example_db.kafka_load ON tbl1
PROPERTIES(
    "desired_concurrent_number"="3",
    "max_batch_interval" = "20",
    "max_batch_rows" = "200000"
)
FROM KAFKA(
    "kafka_broker_list" = "host:9092",
    "kafka_topic" = "topic1",
    "property.kafka_default_offsets" = "OFFSET_BEGINNING"
);

Insert Into(适合小量数据或 ETL 中转)
  • 原理:类似 MySQL 的 INSERT INTO ... SELECT ...

  • 特点:

    • 同步执行,适合 < 100 万行 的小数据量

    • 可用于 Doris 内部表间数据转换(如 DWD → DWS)

  • 限制:

    • 不适合高频写入(会触发小文件问题)

    • 性能远低于 Stream/Broker Load

  • 示例:

sql 复制代码
INSERT INTO tbl_agg
SELECT user_id, sum(pv) FROM tbl_detail GROUP BY user_id;
各导入方式对比总结
导入方式 实时性 吞吐量 数据源 适用场景
Stream Load 秒级 HTTP(本地/程序) 实时日志、Flink 写入
Routine Load 秒级 Kafka 持续实时消费
Broker Load 分钟级 极高 HDFS/S3/OSS 等 T+1 批量导入、大文件
Insert Into 秒级 Doris 内部表 小量数据、ETL 中转
最佳实践建议
  1. 实时场景 → 优先选 Routine Load(Kafka) 或 Stream Load(Flink/日志)

  2. 批量离线导入 → 用 Broker Load(HDFS/S3)

  3. 避免高频 Insert Into → 会导致小文件过多,影响查询性能

  4. 开启 Routine Load 监控 → 通过 SHOW ROUTINE LOAD 查看消费状态

  5. 合理设置 Label → 避免重复导入(Doris 通过 label 保证幂等)

方式 适用场景 吞吐 延迟 是否推荐生产
JDBC INSERT 小量测试、调试 低(几千/秒) ❌(会出多版本问题!)
Stream Load (HTTP) Kafka 消费、日志导入 高(10w+/秒) 秒级 ✅ 强烈推荐
Routine Load 自动消费 Kafka 秒级 ✅(适合简单场景)

📌 血泪教训:

生产环境禁止直接用 JDBC INSERT 写 Doris!

原因:每次 INSERT 生成新版本 → 多版本堆积 → 查询结果混乱


表模型:选对模型,性能翻倍

模型 适用场景 特点 示例
Duplicate Key 日志、事件流 保留所有明细,不聚合 用户点击日志
Unique Key 需要更新的明细表 主键去重,最新覆盖 用户画像表
Aggregate Key 预聚合指标 自动 SUM/COUNT/MAX PV/UV 汇总表

✅ 推荐:

  • 日志分析 → Duplicate Key

  • 用户行为宽表 → Unique Key

  • 报表指标 → Aggregate Key


兼容性:零学习成本

  • 协议兼容:直接用 mysql-connector-java

  • SQL 兼容:支持 JOIN、子查询、窗口函数

  • 工具兼容:Navicat、DBeaver、DataGrip 直接连

🎯 你不需要学新语法,就像操作 MySQL 一样!


Spring Boot 整合实战(避坑版)

依赖配置

xml 复制代码
xml<!-- 核心:用 MySQL 驱动连 Doris -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.33</version>
</dependency>

<!-- 连接池(推荐 Druid) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid-spring-boot-starter</artifactId>
    <version>1.2.16</version>
</dependency>

<!-- MyBatis -->
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>3.0.3</version>
</dependency>

<!-- Stream Load 需要 HTTP 客户端 -->
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
</dependency>

多数据源配置(主库 + Doris)

yaml 复制代码
spring:
  datasource:
    # 主业务库(MySQL)
    primary:
      url: jdbc:mysql://mysql:3306/order_db
      username: root
      password: xxx
    
    # Doris 分析库
    doris:
      url: jdbc:mysql://doris-fe:9030/analysis_db  # 注意:端口是 9030!
      username: root
      password: ""  # 默认无密码

Java 配置(手动控制,避免自动配置冲突)

java 复制代码
// 主启动类:排除 MyBatis 自动配置
@SpringBootApplication(exclude = MybatisAutoConfiguration.class)
public class Application { /* ... */ }
主数据源(MySQL)
java 复制代码
@Configuration
@MapperScan(basePackages = "com.example.mapper.mysql", 
           sqlSessionTemplateRef = "mysqlSqlSessionTemplate")
public class PrimaryDataSourceConfig {

    @Bean 
    @Primary
    @ConfigurationProperties("spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean 
    @Primary
    public SqlSessionFactory mysqlSqlSessionFactory(DataSource ds) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(ds);
        return bean.getObject();
    }

    @Bean 
    @Primary
    public SqlSessionTemplate mysqlSqlSessionTemplate(SqlSessionFactory sf) {
        return new SqlSessionTemplate(sf);
    }
}
Doris 数据源
java 复制代码
@Configuration
@MapperScan(basePackages = "com.example.mapper.doris",
           sqlSessionTemplateRef = "dorisSqlSessionTemplate")
public class DorisDataSourceConfig {

    @Bean
    @ConfigurationProperties("spring.datasource.doris")
    public DataSource dorisDataSource() {
        return DruidDataSourceBuilder.create().build();
    }

    @Bean
    public SqlSessionFactory dorisSqlSessionFactory(DataSource ds) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(ds);
        return bean.getObject();
    }

    @Bean
    public SqlSessionTemplate dorisSqlSessionTemplate(SqlSessionFactory sf) {
        return new SqlSessionTemplate(sf);
    }
}

✅ 关键规则:

  1. 两个 @MapperScan 包路径必须不同

  2. 只有主数据源加 @Primary

  3. 方法名与 @Qualifier 保持一致

最佳实践清单(直接抄作业)

表设计

  • 分区:按天/月分区(PARTITION BY RANGE(event_date)

  • 分桶:按高基数列(如 user_id)分桶,桶数 = BE 节点数 × 10

  • 模型选择:

    • 日志 → Duplicate Key

    • 宽表 → Unique Key

    • 指标 → Aggregate Key

写入规范

场景 推荐方式
Kafka 消费 Stream Load(批量)
文件导入 Broker Load
调试/小量 JDBC(仅限测试环境)

查询优化

  • 避免 SELECT * → 只查需要的列

  • 大表 JOIN 小表 → 小表用 BROADCAST Hint

  • 时间范围必加 → 利用分区裁剪

监控告警

  • 关键指标:

    • Tablet Version Count > 100 → 告警

    • Stream Load 失败率 > 1% → 告警

    • 查询 P99 > 5s → 优化

总结:Doris 使用口诀

"一兼容、二模型、三写入、四分片"

步骤 要点
一兼容 用 MySQL 驱动直连,SQL 零学习成本
二模型 Duplicate(日志)、Unique(宽表)、Aggregate(指标)
三写入 生产只用 Stream Load,禁用 JDBC INSERT
四分片 按时间分区 + 按用户分桶,性能翻倍

相关推荐
春日见8 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
小高不会迪斯科8 小时前
CMU 15445学习心得(二) 内存管理及数据移动--数据库系统如何玩转内存
数据库·oracle
e***8908 小时前
MySQL 8.0版本JDBC驱动Jar包
数据库·mysql·jar
l1t8 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
失忆爆表症10 小时前
03_数据库配置指南:PostgreSQL 17 + pgvector 向量存储
数据库·postgresql
AI_567810 小时前
Excel数据透视表提速:Power Query预处理百万数据
数据库·excel
Elastic 中国社区官方博客10 小时前
如何防御你的 RAG 系统免受上下文投毒攻击
大数据·运维·人工智能·elasticsearch·搜索引擎·ai·全文检索
SQL必知必会11 小时前
SQL 窗口帧:ROWS vs RANGE 深度解析
数据库·sql·性能优化
Gauss松鼠会11 小时前
【GaussDB】GaussDB数据库开发设计之JDBC高可用性
数据库·数据库开发·gaussdb