Doris相关知识点

1. Doris的使用

CREATE TABLE ods_sit.tbl_cust_outbound_collect_order (
tenant_id INT,
collect_date DATE,
waybill_no VARCHAR(64),
receiver_city_code VARCHAR(64),
next_stop_center_name VARCHAR(128),
-- ... 其他列
)
ENGINE=OLAP
DUPLICATE KEY(tenant_id, collect_date, waybill_no)
PARTITION BY RANGE (collect_date) (
PARTITION p20251120 VALUES LESS THAN ('2025-11-21'),
PARTITION p20251121 VALUES LESS THAN ('2025-11-22')
-- 可启用动态分区自动维护
)
DISTRIBUTED BY HASH(waybill_no) BUCKETS 32
PROPERTIES ("replication_allocation" = "tag.location.default: 3");

解释:

  • ENGINE=OLAP 表示使用OLAP引擎存储数据
  • DUPLICATE KEY 定义主键,确保数据不重复
  • PARTITION BY RANGE 按日期范围分区,提高查询效率
    • p20251120表示2025-11-20之前的数据
    • p20251121表示2025-11-20-2025-11-21之间的数据
  • DISTRIBUTED BY HASH 按waybill_no哈希分布,实现并行查询
    • 将数据均匀的打32个桶,桶再落到各个BE节点。
  • PROPERTIES 设置副本分配策略,确保数据高可用
    • “replication_allocation” = “tag.location.default: 3” 表示每个桶在不同BE上维护3个副本,确保高可用与高读并发

2. Doris是什么

他是一款面向现代数据分析需求的实时分析数据库。主要是简化数据分析流程,提高数据查询速度。

Doris结合了MPP(大规模并行处理)架构,能够处理海量数据并实现实时分析。以及OLAP(在线分析处理)引擎,支持复杂的SQL查询。

主要可以用在以下几个场景:

  1. 实时分析场景
    • 例如,电商平台需要实时分析用户行为、订单数据等,以提供及时的决策支持。
  2. 数据仓库
    • 例如,企业需要将分散在不同系统中的数据整合到一个数据仓库中,以支持业务分析和决策。
  3. 报表和可视化分析
    • Doris可以作为报表工具(BI)的后台数据来源,通过SQL接口提供高效的数据查询能力

3. Doris为什么这么强大

  1. 列式存储:大大减少IO操作,提升查询效率。因为大多数查询都只需要访问部分列的数据
  2. 向量化执行引擎:他将传统的一条条处理数据方式批量化,从而进一步提升计算速度和并发处理能力
  3. Bitmap和倒排索引:为了优化对维度数据的查询,提高了查询的性能
  4. 分布式架构:分布式架构可以保证数据可以水平拓展,处理大数据量时依然保证高性能。数据在多个节点间分布,查询任务可以并行执行。
  5. 支持SQL:Doris支持标准的SQL查询语言,用户可以使用熟悉的SQL语句进行数据分析。

4. Doris的架构

  1. FE: 负责用户接口和查询调度
  2. BE:负责数据存储和查询执行
  3. MetaServer:存储和管理元数据
  4. Broker:负责数据导入和导出

5. Doris支持哪些数据导入的方式?

  1. Stream Load:适用于实时导入数据,支持小批量数据、高频的导入场景。(实时监控,在线交易)
  2. Broker Load:适用于大批量数据导入,可以并行导入多个超大文件。(离线数据分析,批量数据处理)
  3. Routine Load:适用于定时导入数据,支持从Kafka、HDFS等数据源中消费数据并导入数据到Doris中。(适合日志数据导入)
  4. Insert Load:适用于表间数据复制,按需数据导入,类似于传统数据库的INSERT语句。(小批量数据导入和表数据复制)
  5. Spark Load:与Apache Spark集成,适用于大规模数据处理和导入,可以利用Spark的并行计算能力。(数据预处理,大数据分析)

5.1 如何使用Broker Load导入数据?

  1. 配置Broker Load任务:在Doris中创建一个Broker Load任务,指定要导入的数据源(如HDFS、S3等)和目标表。
  2. 准备数据文件:将待导入的数据文件上传到指定的数据源路径。
  3. 执行Broker Load任务:在Doris中执行Broker Load任务,将数据从数据源导入到目标表中。
  4. 监控导入进度:可以在Doris中监控Broker Load任务的导入进度,确保数据导入完成。

核心思路:
Broker Load通过SQL提交到Doris FE,在Java侧使用JDBC执行 LOAD LABEL,然后轮询SHOW LOAD 直到 FINISHED/FAILED/CANCELLED

构造LOAD LABEL语句 -> 执行 -> 轮询查询状态 -> 可选取消任务

5.2 如何使用Stream Load导入数据

  1. 准备数据:将待导入的数据准备好,通常是文件形式
  2. 通过HTTP PUT请求上传数据:构建HTTP请求,指定目标数据库和表,并将数据文件作为请求体上传,如:
curl -H "label:test_label" -uuser:passwd -T example_data.txt http://fe_host:8030/api/database_name/table_name/_stream_load
  1. 检查导入状态:通过RESTful API可以查询导入任务的状态

6. RollUP表是什么?

RollUP表是Doris中用于优化查询性能的一种特殊表。他通过预计算和存储聚合结果,减少了查询时的计算量,提高了查询效率。

比如:

ALTER TABLE sales ADD ROLLUP rollup_sales (product_id, SUM(sales_amount), COUNT(*));

如果这时有一个查询

SELECT product_id, SUM(sales_amount), COUNT(*) FROM sales WHERE collect_date = '2025-11-20' GROUP BY product_id;

优化器会优先选择这个RollUP表,而不是直接对原始表进行聚合计算。

7. 如何通过主键模型实现数据更新

在主键模型中,每一行数据必须有一个唯一主键,基于主键系统会进行去重和更新操作。通常使用插入包含相同主键的新数据来触发更新操作。

-- 创建主键模型的表
CREATE TABLE example_table (
id INT PRIMARY KEY,
name STRING,
age INT
) UNIQUE KEY(id) DISTRIBUTED BY HASH(id) BUCKETS 3
PROPERTIES("replication_num" = "3");

-- 插入初始数据
INSERT INTO example_table VALUES (1, 'Alice', 30), (2, 'Bob', 25);

-- 更新数据:主键(id) = 1 的记录将更新 name 和 age 的值
INSERT INTO example_table VALUES (1, 'Alice Smith', 31);

工作机制:

Doris会利用主键进行去重操作。如果主键重复,系统会根据排序键策略来选择保留哪条记录。

8. 物化视图

CREATE MATERIALIZED VIEW view_name AS
SELECT
column1,
COUNT(*) as count,
SUM(column2) as sum_column2
FROM
table_name
GROUP BY
column1;

该视图提前计算了表中column1的计数和column2的总和,当查询该视图时,直接返回预计算的结果,而无需对原始表进行聚合计算。

9. Doris中的数据存储格式都有什么?怎么正确选择

  1. 行存储:数据按行存储,主要用于逐行处理的场景,如OLTP(在线事务处理)场景
  2. 列存储:数据按列存储,主要用于读取大量数据、批量处理和分析场景,如OLAP(在线分析处理)场景

行存储适用于高频次小范围数据写操作,以及对单条数据的高效读取
列存储适合复杂查询,大规模扫描以及聚合操作,减少IO和加速查询性能

另外:可以加入分区和索引。

  • 分区可以让系统更加高效的定位数据
  • 索引可以帮助加速特定查询

10. Doris是如何保证高可用性的

  1. 数据分片和副本:Doris通过这种方式确保数据的高可用性。每个数据分片会有若干个副本,分布在不同的物理节点上。即使单个节点发生故障,系统也能从其他节点读取数据
  2. 节点自动故障转移:一旦某个节点不可用,系统会自动将其上的任务转移到其他运行正常的节点上。
  3. 数据持久化:所有的数据变更都会记录到日志文件中,并且会定期将这些变更持久化到物理存储上。重启时可以通过日志进行数据恢复

11. Doris中的compaction机制是什么?他在数据存储中的作用?

compaction机制是用来进行数据合并和优化的。

  1. 减少数据文件的数量:通过合并小文件,减少存储上的文件碎片,使数据更高效
    • Doris在执行Insert或其他数据写入操作时,数据会分散到多个文件中。如果不进行压缩操作,文件数量会迅速增加,不仅浪费存储空间,还影响查询性能。
    • compaction机制会定期扫描这些小文件,把他们合并为更大的文件
  2. 提升数据读取性能:合并压缩后的文件通常更加紧凑,可以减少IO操作
    • 小文件读取时需要多次IO,但是把这些小文件合并成一个或几个大文件,就可以减少IO次数
  3. 释放存储空间:删除重复数据或无用数据

压缩分为两种类型,一种是全量一种是增量。
全量压缩相对耗时,但是能显著优化存储和查询性能
增量压缩比较轻便,主要在持续写入数据的过程中,合并一些新生成的小文件。

12. Doris数据导入性能如何优化?

  1. 批量导入:尽可能将数据分批次导入,而不是逐条插入。批量操作减少IO次数
    • 可以利用Doris的Stream Load、Broker Load等方式实现
  2. 数据排序:导入前对数据进行排序,减少导入过程中数据的拆分和移动
    • 把相近的数据放在一起,提升查询和导入效率
  3. 适当配置:根据数据量大小和硬件配置调整Doris导入参数。比如:并行度,缓存大小,导入速率等。
  4. 资源隔离:在有条件的情况下,可以为不同导入任务分配独立的计算和存储资源,避免资源争夺
  5. 压缩和编码:采用合适的压缩和编码方式来减少数据带入过程中的带宽和存储压力

13. 聚合表和明细表是什么?

  • 明细表
    • 表模型为DUPLICATE KEY 按照排序键存原始行,不做任何预聚合
    • 同一键的多行共存,查询时需要自己写 GROUP BY 或者 聚合函数
CREATE TABLE tbl_order_detail (
tenant_id INT,
collect_date DATE,
waybill_no VARCHAR(64),
collect_weight DECIMAL(10,2)
)
ENGINE=OLAP
DUPLICATE KEY(tenant_id, collect_date, waybill_no);
  • 聚合表
    • 表模型为AGGREGATE KEY 为度量列指定聚合函数(SUM/MIN/MAX)
    • 写入时,具有相同排序键的行会按照聚合函数合并为一行,查询直接读取已汇总的结果
CREATE TABLE tbl_order_daily_agg (
tenant_id INT,
collect_date DATE,
receiver_city_code VARCHAR(64),
order_cnt BIGINT SUM,
total_weight DECIMAL(18,2) SUM
)
ENGINE=OLAP
AGGREGATE KEY(tenant_id, collect_date, receiver_city_code);

聚合表和明细表有什么区别?

  • 明细表
    • 存储原始行数据,不做任何预聚合
    • 同一键的多行共存,查询时需要自己写 GROUP BY 或者 聚合函数
  • 聚合表
    • 存储预聚合后的结果,每个键只有一行
    • 查询时直接读取已汇为的结果,无需自己写 GROUP BY 或者 聚合函数

14. Doris是如何处理数据一致性的?有哪些数据一致性模型?

  1. 事务机制:Doris支持分布式事务,可以保证在事务范围内的数据具有ACID特性。通过多阶段提交协议(如:2PC,两阶段提交)来保证事务的一致性
  2. 数据复制:Doris通过多副本机制来提升数据的可用性和一致性。每份数据会同时存在于多个副本上,通过一致性协议(如:Raft、Paxos)来管理这些副本,确保读写的一致性
  3. 读写隔离:支持MVCC

15. Doris使用外部表查询其他数据源

CREATE EXTERNAL TABLE mysql_table (
id INT,
name STRING,
age INT
)
ENGINE=ODBC
PROPERTIES (
"host" = "mysql_host",
"port" = "3306",
"user" = "mysql_user",
"password" = "mysql_password",
"database" = "mysql_db",
"table" = "mysql_table_name"
);

之后就可以直接用SQL查询这个外部表了,就像查询普通表一样

SELECT * FROM mysql_table WHERE age > 18;

16. Doris如何进行数据处理和删除?常见更新策略有哪些?

Doris是专门为大数据分析和OLAP场景设计的。处理数据更新和删除在Doris中相对复杂,因为他的设计初衷就是为了数据分析优化的。

  1. 数据更新和删除:通过主键模型,支持数据的更新和删除操作。
  2. 常见的更新策略:
    1. 覆盖更新:直接用新数据替换旧数据。适用于不需要保留历史数据的场景。
    2. 聚合更新:每个聚合键只保留聚合后的结果
    3. 追加更新:不更新,保留所有的导入的数据,允许重复

17. 什么叫谓词下推

将过滤条件尽可能地推到离数据存储最近的地方去执行,尽早地尽可能多的过滤掉不必要的数据

比如:

select name from table where age > 10

传统的做法是先读取一整行数据(包含所有列),在判断age是否大于10.
而Doris只会先读取age这一列的数据,在列式存储格式下快速过滤出满足条件的行的位置(rowid),然后只根据这些rowid去读取name列

18. 聚合模型的配置

CREATE TABLE example_table (
user_id BIGINT,
item_id BIGINT,
quantity BIGINT SUM,
price DOUBLE SUM
)
AGGREGATE KEY(user_id, item_id)
DISTRIBUTED BY HASH(user_id, item_id) BUCKETS 10;

quantity和price字段会以sum的方式进行预聚合,从而提升后续查询的效率

19. Doris是如何处理大规模并发查询的?有哪些常见的并发优化策略

  1. 分布式架构:Doris采用无共享架构,数据与计算分布在多个节点上,查询请求能够很自然的进行分布式处理,从而提高并发处理能力。
  2. 向量化执行:Doris使用向量化执行引擎,将批处理与流水线方式结合,大幅度提高查询执行效率,从而提高并发负载
    • 传统方式:逐行处理
    • 向量化方式:按批处理
  3. 查询调度和资源管理:通过查询队列、优先级、限流等手段合理利用系统资源,保证高并发环境下的服务质量
  4. 缓存机制:Doris内置多级缓存,包括热数据缓存,查询结果缓存等,多次查询相似数据时可以大幅度减少读取开销,提高整体并发能力
  5. 列存储格式:支持列存储(不多赘述)

20. Doris如何配置数据压缩机制

  1. 找到fe.conf或be.conf文件。
  2. 在配置文件中找到compression_type。常见的压缩类型包括SNAPPY、LZ4F、ZSTD等。默认值为SNAPPY。
  3. 重启Doris FE和BE节点使配置生效。
# 编辑 fe.conf 或 be.conf 文件
compression_type = LZ4F # 这里选择 LZ4F 作为压缩算法
  • LZ4F:压缩速度快,解压速度更快,适合实时查询和频繁访问的数据
  • ZLIB:压缩率高,但压缩和解压缩的速度慢,适合存储不常访问的数据
  • SNAPPY:中庸

21. Doris如何通过分布式架构实现水平拓展?有哪些拓展方式

主要体现在两个方面:数据分片计算节点的增加

  • 数据分片:Doris将数据分布在多个节点上没通过分片将数据分散存储,达到负载均衡的效果。当需要扩容时,新增数据节点并将部分数据迁移到
    新节点上,这样每个节点的数据量减少,查询和处理速度也会提高。
  • 计算节点的增加:Doris通过增加计算节点(BE节点)来提升整体的处理能力。新增节点后,系统提供过一致性哈希等算法重新分配计算任务,确保负载均衡