背景
最近业务侧反馈,第三方系统连接我们 Doris 数据库进行数据同步时,查询频繁超时。当前 Doris 集群的 query_timeout 设置为 600 秒(10 分钟) ,第三方要求将超时时间提升到 1800 秒(30 分钟)【其实之前是300秒(5分钟)已经给他们加过一次了!!!】。
乍一看,这只是改个配置参数的事,但仔细分析后,这件事远没有那么简单。
一、先看现状
登录 Doris,执行以下 SQL 查看当前配置:
sql
SHOW VARIABLES LIKE "%query_timeout%";
查询结果如下:
| Variable_name | Value | Default_Value | Changed |
|---|---|---|---|
| query_timeout | 600 | 900 | 1 |
可以看到:
-
当前生效值:600 秒
-
默认值:900 秒
-
Changed = 1:说明这个值曾被人为修改过(从默认 900 改到了 600) 有人可能会说,这不就是改个参数的事吗?直接执行:
sql
SET GLOBAL query_timeout = 1800;
技术上确实能改,但能不能改、该不该改、怎么改,是三个完全不同的问题。
二、直接改超时时间的风险分析
2.1 资源被长查询"绑架"
Doris 的查询超时机制,本质上是一道资源保护防线。每条查询在执行期间会占用:
-
内存: 简单的查询可能只占用几十 MB,但每条查询在执行期间受内存限制 (
exec_mem_limit,默认 2GB/节点)的约束,也就是系统允许它最多使用 2GB。在分布式场景下,如果查询涉及多个节点并行计算,其实际可能占用的总内存往往是该限制值的数倍。 -
CPU 计算资源
-
BE 节点的磁盘 IO 一旦放宽超时到 1800 秒,意味着一条 SQL 可以合法地占用资源长达 30 分钟。如果第三方同时发起多条查询:
| 场景 | 并发数 | 单条查询的内存上限 | 总内存占用上限 |
|---|---|---|---|
| 当前(600s) | 3 | 2GB | 6GB |
| 放宽(1800s) | 3 | 2GB | 6GB(但持有时间×3) |
| 单看并发数可能差别不大,但内存占用时长直接翻了 3 倍,意味着其他业务查询排队等待的概率大幅增加。 |
2.2 治标不治本------"超时不够就加超时"
今天是 600 → 1800,明天数据量翻倍,是不是要改成 3600?后天呢? 超时时间没有上限,但集群资源是有上限的。 如果一条 SQL 需要跑 30 分钟才能返回结果,真正要解决的不是"给它更多时间",而是**"为什么它要跑这么久"**。
2.3 第三方查询可能存在性能问题
一条正常的同步查询,如果需要 30 分钟,大概率存在以下问题:
-
全表扫描:没有加分区过滤条件,每次同步全量读取
-
无分页机制 :一次性
SELECT * FROM table拉取百万级数据 -
缺少索引/分区裁剪:查询未命中 Doris 的排序键或分区键
-
SELECT * 滥用:大量无用字段增加了 IO 和内存开销
2.4 多 FE 节点配置不一致的坑
实际操作中还发现一个"坑":执行 SET GLOBAL query_timeout = 900 后,新建连接查到的值仍然是 600。 原因是 Doris 集群有多个 FE 节点 ,通过负载均衡连接时,每次可能打到不同的 FE。SET GLOBAL 只对当前 FE 生效,不会自动同步到其他 FE。
TypeScript
┌──────────────┐
│ 负载均衡器 │
└──────┬───────┘
│
┌────┴────┐
▼ ▼
FE-1 FE-2 ← SET GLOBAL 只改了一个,另一个还是旧值
彻底解决需要修改 fe.conf 配置文件并重启所有 FE 节点,这对线上集群来说是有变更风险的操作。
三、正确的处理流程
3.1 技术改配置是最后一步,不是第一步
强烈建议按以下流程推进,而不是"说改就改":
TypeScript
第三方提需求/提单
↓
开发评估影响范围
↓
领导层审批决策
↓
DBA/开发执行变更
↓
变更后监控验证
为什么不能直接改?
-
变更必须留痕:没有工单、没有审批,出了问题谁来背锅?
-
影响评估必须做:改了之后对其他业务有没有影响?对集群资源有没有压力?需要有书面评估。
-
回滚方案必须有:改完发现扛不住,怎么快速回滚?改 fe.conf 重启 FE 需要多久恢复?
3.2 治标不如治本:让第三方优化代码(重点)
超时时间只是表象,查询优化才是根本。 既然慢,就得优化 SQL。我们可以给第三方提具体的技术要求,而不是无底线加超时。
(1)拒绝深分页,改用游标分页(Keyset Pagination)
游标分页(Keyset Pagination)真的万能吗?聊聊它的限制和替代方案
对于大数据量同步,传统的 LIMIT offset, size 越往后越慢。推荐用游标分页,记录上一批数据的最大 ID,下一批直接往后查。
错误示范(深分页):
sql
-- 这种写法扫到后面会非常慢
SELECT * FROM table_name WHERE dt = '2025-07-01' LIMIT 100000, 10000;
正确做法(游标分页):
sql
-- 第一批
SELECT * FROM table_name WHERE dt = '2025-07-01' ORDER BY id LIMIT 10000;
-- 第二批(假设上一批最后一条 id 是 10000)
SELECT * FROM table_name
WHERE dt = '2025-07-01' AND id > 10000
ORDER BY id LIMIT 10000;
优势:无论翻到多少页,每次查询都只扫描一页数据,耗时稳定在秒级。
(2)利用分区裁剪
确保查询条件命中 Doris 的分区键:
sql
-- 正确:带分区条件
SELECT * FROM table_name WHERE dt = '2025-07-01';
-- 错误:不带分区条件,全分区扫描
SELECT * FROM table_name;
(3)增量同步替代全量同步
如果业务允许,建议使用增量同步机制:
-
利用
update_time或modify_time字段筛选变更数据 -
结合消息队列(如 Kafka)做实时变更捕获(CDC),而非定时全量拉取
3.3 如果确实需要调整超时时间
在第三方完成优化之前,作为过渡方案,可以考虑用户级别的精细化控制:
sql
-- 仅对第三方专用账号生效,不影响业务用户
ALTER USER 'third_party_user' SET PROPERTY 'query_timeout' = '1800';
这样做的好处:
-
隔离影响:业务用户的查询超时仍然是 600s,不受影响
-
责任清晰:如果该用户的长查询出了问题,可以快速定位
-
可追溯:用户级别的配置修改有明确的归属
四、总结
| 维度 | 建议 |
|---|---|
| 能否直接改 | 能,但不建议跳过审批流程直接改 |
| 改哪里 | 优先用户级 ALTER USER,避免全局 SET GLOBAL |
| 怎么改 | 走变更流程:提单 → 评估 → 审批 → 执行 → 监控 |
| 根本解决 | 推动第三方做查询优化:游标分页、分区裁剪、增量同步 |
| 多 FE 问题 | 修改 fe.conf + 重启所有 FE 节点,确保全局一致 |
核心观点:
- 超时时间是一道安全阀,而不是用来"兜底"的配置。当一条查询需要 30 分钟才能跑完时,问题不在超时太短,而在于查询本身需要被优化。
- 今天可以改到 1800,明天数据量翻倍是不是要改到 3600?数据量会增长,但集群资源不会无限增长。 把压力推给基础设施永远是最简单但最危险的做法。
- 正确的做法是:第三方优化查询,开发评估影响,领导决策审批,DBA 规范变更。 各司其职,才能长期稳定。
五、补充一下doris的FE(Frontend) 和BE(Backend)
5.1 核心定义
- FE(Frontend,前端节点) :Doris集群的"大脑 ",负责元数据管理、集群调度、查询解析。
- BE(Backend,后端节点) :Doris集群的"肌肉 ",负责数据存储、查询计算、数据导入。
5.2 核心职责差异
| 组件 | 核心职责 | 通俗比喻 |
|---|---|---|
| FE | 1. 存储元数据(表结构、分区信息、副本分布、用户权限等); 2. 解析SQL,生成查询计划; 3. 负载均衡,将查询任务分配给BE; 4. 管理集群节点(FE/BE的加入、退出、状态监控)。 | 公司管理层:规划任务、分配资源、监控进度。 |
| BE | 1. 存储实际数据(表数据、索引文件等); 2. 并行执行查询计算(如过滤、聚合、排序); 3. 处理数据导入(如INSERT、LOAD); 4. 返回计算结果给FE,由FE汇总后返回客户端。 | 员工:执行具体任务、产出结果。 |
5.3、数量与特点
-
FE节点:
- 通常有1个主节点(Master FE) + 多个从节点(Follower FE)(用于高可用,避免单点故障);
- 不存储用户数据,仅存储元数据(占用磁盘小);
- 负责集群的"指挥",自身故障不会导致数据丢失(但会影响集群管理)。
-
BE节点:
- 可有多个节点(数量取决于数据量和计算需求);
- 存储用户数据(占用磁盘大,是数据存储的核心);
- 节点故障可能导致部分数据不可用(但通过副本机制保证高可用)。
5.4 总结
- FE是"管理者":负责规划、调度,不碰数据;
- BE是"执行者":负责存储、计算,产出结果;