Doris 2.1 BE节点内存打满时,核心定位思路是先锁定内存占用高的源头(查询/导入/系统组件),再定位具体SQL,最后分析SQL触发内存溢出的根因。以下是分步骤、可落地的定位方法,适配Doris 2.1版本特性:

一、紧急定位:快速找到当前占用内存的SQL(BE内存未OOM时)

若BE还未宕机,优先通过Doris内置工具定位实时内存消耗高的SQL,这是最高效的第一步。

1. 查看运行中/最近结束的查询(核心)

登录Doris FE节点,执行以下命令,筛选内存占用Top SQL:

-- 1. 查看正在执行的查询列表,当前正在运行的 SQL 语句。
SHOW PROC '/current_queries';

-- 关键字段说明:
-- QueryId:查询唯一标识(格式 xxxx-xxxx),用于定位、终止查询(KILL QUERY),结合 BE 日志排查内存消耗细节。
-- ConnectionId:客户端与 FE 的连接 ID,0 表示 Doris 内部任务(物化视图刷新、Compaction 等),非 0 为业务客户端发起的查询。
-- Catalog:查询所属数据目录,internal 为 Doris 内置 Catalog,其他为自定义外部 Catalog(如 Hive Catalog)。
-- Database:查询目标数据库名,空值表示未指定数据库。
-- User:发起查询的 Doris 用户名,用于定位业务归属、限制用户维度内存 / 并发。
-- ScanBytes:查询已扫描字节数,N/A 表示未开始扫描数据或非数据扫描类查询,数值单位为字节。
-- ProcessRows:查询已处理行数,N/A 表示未开始处理数据,数值为具体行数。
-- ExecTime:查询执行时长(单位:秒),ExecTime>300 秒的超长查询是内存打满高风险对象。

-- 2.  返回当前正在执行的 query。
SHOW PROC '/current_query_stmts' \G;
-- 补充:Doris 2.1当前,Doris 系统默认将执行时间超过 5 秒的 SQL 认定为慢 SQL,此阈值可通过 config.qe_slow_log_ms 进行配置。

筛选规则

  • 优先看ScanBytes/ProcessRow值很大(如GB以上,千万、亿以上)的SQL;
  • 关注运行时长极长(如超过1小时)的RUNNING状态SQL,这类SQL大概率是内存堆积的元凶。

2. 通过BE监控面板定位(可视化更直观)

Doris 2.1默认集成Prometheus+Grafana监控,直接查看BE内存相关面板:

  • 核心监控指标

    • doris_be_memory_allocated_bytes:BE 进程物理内存大小,取自 /proc/self/status/VmRSS;
    • doris_be_memory_jemalloc:Jemalloc stats, 取自 je_mallctl。含义参考:https://jemalloc.net/jemalloc.3.html;
    • doris_be_memory_pool_bytes_total:所有 MemPool 当前占用的内存大小。统计值,不代表真实内存使用。;
  • 告警阈值:若doris_be_memory_allocated_bytes短时间内飙升至BE总内存的80%以上,对应时间段的SQL即为可疑对象。

在这里插入图片描述

3. 查看BE节点系统层面的进程内存

登录BE节点服务器,通过系统命令辅助定位:

# 1. 查看BE进程的内存占用(确认是否是BE本身占满内存)
top -p $(pidof doris_be)
# 关注RES(物理内存)、VIRT(虚拟内存),若RES接近物理内存(如32G节点RES=30G),说明BE进程内存溢出

# 2. 按线程拆分BE内存占用(定位BE内耗内存的线程)
ps -mp $(pidof doris_be) -o THREAD,tid,pcpu,rsize(或者rss) | sort -k5 -r
# rsize列是线程内存占用,若某线程rsize远超其他,结合BE日志可定位到具体算子(如Join/GroupBy)

在这里插入图片描述

二、事后定位:BE已OOM/宕机,从日志回溯SQL和原因

若BE已因内存打满宕机,需从日志中提取关键信息,回溯触发OOM的SQL:

1. 查看BE核心日志(最关键)

Doris 2.1 BE日志默认路径:${DORIS_HOME}/be/log/,核心日志文件:

  • be.INFO:包含所有查询、导入的执行日志,以及内存分配失败的报错;
  • be.WARNING/be.ERROR:包含内存溢出、资源不足的关键报错。

搜索关键词定位

# 1. 搜索OOM/内存分配失败的报错(直接定位触发OOM的SQL)
dmesg -T|grep memory
grep -i "MEM_LIMIT_EXCEEDED" be.INFO
grep -i "Process Memory Summary" be.INFO
grep -i "Memory Tracker Summary" be.INFO

# 2. 搜索QueryId(从报错中提取QueryId,再回溯完整SQL)
grep "QueryId: [0-9a-f]*" be.INFO | grep -A 10 "memory"

典型报错示例

ERROR 1105 (HY000): errCode = 2, detailMessage = (10.16.10.8)[MEM_LIMIT_EXCEEDED] xxxx .

从报错中可直接获取:

  • 当查询和导入的报错信息中出现 MEM_LIMIT_EXCEEDED 时,说明任务因为进程可用内存不足,或任务超过单次执行的内存上限而被 Cancel。
  • 若报错信息包含 Process memory not enough,说明进程可用内存不足。
  • 若报错信息中出现 memory tracker limit exceeded 时,说明任务超过单次执行内存限制。

2. 查看FE慢查询日志(补充定位)

FE日志路径:${DORIS_HOME}/fe/log/,慢查询日志文件:fe.audit.log,记录了所有慢查询的完整SQL、执行时长、内存峰值、涉及的BE节点等:

grep '2025-11-27 13' fe.audit.log|grep slow_query   # 按扫描数据量大小峰值降序排列

日志示例

2025-09-10 10:20:00,123 [INFO] slow_query: QueryId=987654321, User=admin, Db=test, Sql=SELECT COUNT(*) FROM big_table GROUP BY high_cardinality_col;, StartTime=2025-09-10 10:10:00, Duration=1380s, PeakMemory=31GB, BEs=192.168.1.101

3. 查看FE慢查询日志(SQL版)

__internal_schema.audit_log审计日志表,记录了所有慢查询的完整SQL、执行时长、内存峰值、涉及的BE节点等:

select scan_bytes /1024/1024/1024 as mem_used_gb
	FROM
    `__internal_schema`.`audit_log` partition(p20251127)
	where query_time > 300
	order by scan_bytes desc
	limit 10;
   # 按扫描数据量大小峰值降序排列

三、分析SQL触发内存打满的根因(针对定位到的SQL)

找到具体SQL后,需分析其为何消耗大量内存,Doris 2.1中常见根因及验证方法:

1. 检查SQL本身的执行计划(核心)

对定位到的SQL执行EXPLAIN,分析执行计划中的内存密集型算子:

EXPLAIN SELECT COUNT(*) FROM big_table GROUP BY high_cardinality_col;

关键分析点

  • 是否有HASH GROUP BY:Hash分组会将所有分组键加载到内存哈希表,高基数列(如手机号、UUID)会导致哈希表爆炸;
  • 是否有HASH JOIN:未加ON条件的笛卡尔积、大表Join小表(未广播小表)会加载大量数据到内存;
  • 是否有全表扫描:未加分区过滤(如WHERE dt='2025-09-10')的全表扫描,加载数据量过大;
  • 是否有ORDER BY/DISTINCT:这类操作会将结果集全量加载到内存排序/去重。

2. 验证表结构/数据分布问题

-- 1. 查看表的分区分桶(是否合理)
SHOW CREATE TABLE big_table;
-- 问题点:分区粒度太大(如按年分区)、分桶数过少(数据倾斜)

-- 2. 查看数据倾斜(Join/GroupBy的键是否倾斜)
SELECT high_cardinality_col, COUNT(*) FROM big_table GROUP BY high_cardinality_col LIMIT 10;
-- 若某值的COUNT(*)占总数据的50%以上,说明数据倾斜,导致单BE节点处理过多数据

-- 3. 查看数据版本(版本过多会增加内存占用)
SHOW PROC '/dbs/test/tables/big_table/versions';
-- 版本数超过100个,说明Compaction未及时执行,多版本数据占用内存

3. 检查Doris 2.1配置是否合理

# 查看BE核心内存配置(be.conf)
grep -E "mem_limit|be_memory_limit|block_cache_size|exec_mem_limit" be.conf

常见配置错误

  • mem_limit:描述:限制 BE 进程使用服务器最大内存百分比。用于防止 BE 内存挤占太多的机器内存,该参数必须大于 0,当百分大于 100% 之后,该值会默认为 100%;默认值:90%。
  • exec_mem_limit:导入内存限制。默认为 2GB。单位为字节。

四、快速止损+长期优化

1. 临时止损(BE未宕机)

-- 终止高内存查询(替换为实际QueryId)
KILL QUERY '987654321';

-- 临时调整单查询内存限制(FE执行,全局生效)
SET GLOBAL mem_limit = '4G';

2. 长期优化(针对根因)

根因类型优化措施
高基数GROUP BY/Join1. 加分区过滤;2. 拆分高基数列;3. 改用Shuffle Join(避免Hash Join);4. 开启分区裁剪/索引
数据倾斜1. 调整分桶键(避免倾斜);2. 使用随机数打散倾斜键(如col + rand()%10);3. 增加分桶数
配置不合理1. mem_limit设为物理内存的80%;2. exec_mem_limit设为2-4G
版本过多1. 调整Compaction配置,被所有的 compaction 任务所能持有的 “permits” 上限,用来限制 compaction 占用的内存。(total_permits_for_compaction_score);2. 手动触发Compaction:ADMIN COMPACT TABLE big_table;
内存泄漏(Doris 2.1 bug)1. 升级到Doris 2.1.5+(修复了Hash Join/导入的内存泄漏bug);2. 定期重启BE(每周一次,临时释放内存)

总结

Doris 2.1 BE内存打满的定位核心是:先通过SHOW PROC/监控找到高内存SQL → 再通过日志/执行计划分析根因 → 最后针对性优化SQL/配置/表结构。优先排查查询层面的问题(80%的内存打满由不合理SQL导致),其次是配置和数据分布,最后考虑版本bug/内存泄漏。

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐