【大数据Doris】生产环境,Doris主键模型全表7000万数据更新写入为什么那么慢?

公司在 Apache Doris 的生产实践中,发现在做数据需求时候,遇到这样一个"致命"问题:

复制代码
"一张 7000 万行的主键模型账单表,执行全表 INSERT 时,不仅写入慢得像蜗牛,还把整个 BE 节点拖到 CPU 100%、IO 打满,集群几乎瘫痪。"

今天这篇文章用来记录下这个问题,且做详细剖析,并给出一套可落地、高性价比的优化方案。

首先,我从Doris官网了解到,这并非Doris的缺陷,而是主键模型(Unique Key / Primary Key)的写入机制与全量导入场景天然不匹配。以下是进行问题分析和问题解决。

一、为什么主键模型 INSERT 这么慢?------ 根本原因

Doris 的主键模型(特别是 Merge-on-Write 实现)在写入时必须保证数据唯一性,因此采用 "读-改-写"(Read-Modify-Write) 机制:

python 复制代码
INSERT INTO t_bill_center VALUES (id=1001, ewb_no ='010010101099')
        ↓
1. 查找 id=1001 是否已存在(需扫描主键索引)
2. 若存在 → 在 delete_bitmap 中标记旧记录为"删除"
3. 再将新记录写入 MemTable

关键性能瓶颈:

瓶颈点 技术细节 影响
delete_bitmap 维护 每次更新都要修改位图(tablet_meta.cpp:763) 内存压力大,频繁 GC
MemTable 冲突 多线程写同一 tablet 时锁竞争(tablet.cpp:363) 并发写入吞吐骤降
无批量合并 默认每条 INSERT 独立提交 网络 + 日志开销爆炸
Compaction 压力 高频写入触发大量 Delta Compaction IO 打满,查询变慢

一句话总结:

主键模型是为"实时更新"设计的,不是为"全量覆盖"准备的。

二、核心优化方案:启用 Group Commit(攒批提交)

Doris 从 1.2 版本 开始引入 Group Commit 功能,专为解决高频小写入场景的性能问题。它能将多个 INSERT 请求自动攒批、合并提交,大幅降低事务开销。

启用方式(两种)

方式 1:建表时指定(推荐)

python 复制代码
CREATE TABLE t_bill_center (
    user_id BIGINT,
    ewb_no VARCHAR(100),
    email VARCHAR(100)
) ENGINE=OLAP
UNIQUE KEY(user_id)
DISTRIBUTED BY HASH(user_id) BUCKETS 64
PROPERTIES (
    "group_commit_interval_ms" = "10000",      -- 每 10 秒提交一批
    "group_commit_data_bytes" = "134217728"   -- 或累计 128MB 提交
);

方式 2:全局 FE 配置(fe.conf)

python 复制代码
# 默认值(Config.java:646-652)
group_commit_interval_ms = 10000
group_commit_data_bytes = 134217728  # 128MB

原理:

Group Commit 在 BE 端维护一个内存队列(group_commit_queue_mem_limit),当达到时间或大小阈值时,一次性将多条 INSERT 合并为一个事务提交,减少 WAL 写入和锁竞争。

三、BE 层关键参数调优(be.conf)

主键模型对内存和 IO 极其敏感,以下配置可显著提升稳定性:

python 复制代码
# 1. 增大写缓冲(默认 200MB,5000 万数据建议 ≥ 500MB)
write_buffer_size = 536870912  # 512MB

# 2. 启用自适应缓冲(根据负载动态调整)
enable_adaptive_write_buffer_size = true

# 3. 控制并行 flush 任务数(避免 IO 打满)
memtable_flush_running_count_limit = 2

# 4. Group Commit 队列内存(默认 64MB)
group_commit_queue_mem_limit = 268435456  # 256MB

# 5. Group Commit 处理线程(根据 CPU 核数调整)
group_commit_insert_threads = 8

# 6. WAL 磁盘限制(防止日志占满磁盘)
group_commit_wal_max_disk_limit = 10%

注意:

复制代码
write_buffer_size 过大会导致 OOM,建议不超过 BE 节点内存的 20%。

四、终极建议:换用更高效的导入方式

对于 7000 万级全量数据,绝对不要用 INSERT INTO ... VALUES (...)!这是性能灾难的根源。

推荐方案:Stream Load + 分批导入

步骤 1:将数据拆分为多个文件(如每份 200 万行)

python 复制代码
split -l 2000000 full_data.csv chunk_
# 生成 chunk_aa, chunk_ab, ...

步骤 2:使用 Stream Load 并行导入

python 复制代码
# 示例:导入一个分片
curl --location-trusted -u user:passwd \
    -H "label:load_20240601_aa" \
    -H "column_separator:, " \
    -T chunk_aa \
    http://fe_host:8030/api/lbdb/t_bill_center/_stream_load

优势:

复制代码
性能提升 5~10 倍(Stream Load 专为批量设计)
自动重试 + 断点续传
不占用 MySQL 协议连接池

对比:

    INSERT:单连接,逐条解析,事务开销大
    Stream Load:HTTP 并行,批量解析,零事务开销

五、如果必须用 INSERT?------ 安全分批策略

若因架构限制只能用 INSERT,请务必分批 + 限流:

python 复制代码
-- 错误示范(直接全量插入)
INSERT INTO t_bill_center SELECT * FROM temp_table;

-- 正确做法:循环分页插入
INSERT INTO t_bill_center
SELECT * FROM temp_table 
ORDER BY user_id 
LIMIT 100000 OFFSET 0;   -- 第1批

INSERT INTO t_bill_center
SELECT * FROM temp_table 
ORDER BY user_id 
LIMIT 100000 OFFSET 100000; -- 第2批
-- ... 循环直到完成

同时配合:

复制代码
    应用层加 sleep(1s) 避免压垮 BE
    监控 show proc '/backends' 内存使用

六、监控与诊断:如何判断优化是否生效?

关键监控命令:

python 复制代码
-- 1. 查看 BE 节点状态(重点关注 Mem、IO)
SHOW PROC '/backends';

-- 2. 查看 Compaction 任务是否堆积
SHOW PROC '/compaction';

-- 3. 查看 Group Commit 队列(Doris 2.0+)
SHOW PROC '/group_commit';

七、架构升级建议:Doris 2.0+ 用户必看

如果你使用的是 Doris 2.0 或更高版本,强烈建议:

复制代码
迁移到 Primary Key 模型(非 Unique Key)
    新主键模型使用 Memory + RocksDB 存储索引
    写入性能比旧版提升 3~5 倍
    支持 Partial Update(只更新部分列)

开启 Light Schema Change
    避免 ALTER TABLE 锁表

八、总结:优化 checklist

优化项 操作 预期效果
启用 Group Commit 建表加 PROPERTIES 写入吞吐 +200%
调大 write_buffer_size be.conf 配置 减少 flush 频率
换用 Stream Load 分批 HTTP 导入 避免集群卡死
分批 INSERT LIMIT + OFFSET 降低瞬时压力
升级 Doris 2.0+ 使用 Primary Key 根本性性能提升

最后说明:

"主键模型 ≠ 全量导入工具"。

用对场景(实时更新),才能发挥 Doris 的真正威力。

相关推荐
优雅的潮叭13 小时前
c++ 学习笔记之 shared_ptr
c++·笔记·学习
Gofarlic_oms113 小时前
Windchill用户登录与模块访问失败问题排查与许可证诊断
大数据·运维·网络·数据库·人工智能
claider13 小时前
Vim User Manual 阅读笔记 usr_08.txt Splitting windows 窗口分割
笔记·编辑器·vim
am心13 小时前
学习笔记-用户下单
笔记·学习
Zoey的笔记本14 小时前
2026告别僵化工作流:支持自定义字段的看板工具选型与部署指南
大数据·前端·数据库
Wpa.wk14 小时前
性能测试 - 搭建线上的性能测试环境参考逻辑图
java·经验分享·测试工具·jmeter·性能测试
lingling00914 小时前
2026 年 BI 发展新趋势:AI 功能如何让数据分析工具 “思考” 和 “对话”?
大数据·人工智能·数据分析
鹧鸪云光伏14 小时前
光伏项目多,如何高效管理?
大数据·人工智能·光伏
冬奇Lab14 小时前
稳定性性能系列之十六——车机特定场景:黑卡死问题分析与排查实战
android·性能优化
Acrel1870210670614 小时前
浅谈电气防火限流保护器设计在消防安全中的应用价值
大数据·网络