You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apache Doris执行SQL触发内存超限错误,如何解决?

Apache Doris 内存超限问题排查与优化方案

问题场景

使用Apache Doris 2.1.5集群(3FE+3BE,单BE内存64GB),创建UNIQUE KEY表并导入约100GB数据后,执行全局分组排序查询时触发内存超限错误:

process memory used 48.26 GB exceed limit 50.21 GB or sys available memory 1.54 GB less than low water mark 1.60 GB.

同时无法定位集群中哪个查询占用内存最高,以下是排查与优化方案:


一、定位高内存查询

1. 通过FE Web UI查询

访问FE节点的Web UI(默认端口8030),进入Query页面,按Memory Used列排序,直接查看运行中查询的内存占用情况,找到Top内存消耗查询。

2. 通过系统表查询

在FE执行SQL查询系统元数据表,获取运行中查询的内存详情:

SELECT query_id, query_sql, memory_used, state 
FROM information_schema.queries 
WHERE state = 'RUNNING' 
ORDER BY memory_used DESC;

3. 通过BE日志定位

查看BE节点的日志文件(默认路径${DORIS_HOME}/log/be.INFO),搜索memory exceed关键词,找到触发错误的查询ID和对应的SQL语句。


二、避免内存超限的优化方案

1. 查询语句层面优化

  • 添加分区过滤:如果业务不需要全量数据,在查询中指定date分区范围,减少扫描的数据量:
    SELECT user_id, count(1) as c 
    FROM my_table_name 
    WHERE date >= '2017-01-01' AND date < '2017-03-01'
    GROUP BY user_id 
    ORDER BY c DESC;
    
  • 限制单查询内存:执行查询前设置exec_mem_limit,避免单查询占用过多内存:
    SET exec_mem_limit = '32G'; -- 根据BE内存调整,建议不超过单BE内存的50%
    SELECT user_id, count(1) as c FROM my_table_name GROUP BY user_id ORDER BY c DESC;
    
  • 减少排序内存开销:如果不需要全量排序结果,添加LIMIT限制返回行数:
    SELECT user_id, count(1) as c 
    FROM my_table_name 
    GROUP BY user_id 
    ORDER BY c DESC LIMIT 1000;
    

2. 表结构与数据分布优化

  • 调整分桶数:当前表分桶数为16,3BE节点建议设置分桶数为节点数的整数倍(如18),确保分桶均匀分布在BE节点,避免单节点计算压力过大:
    ALTER TABLE my_table_name SET DISTRIBUTED BY HASH(`user_id`) BUCKETS 18;
    
  • 优化数据倾斜:检查是否存在热点user_id导致单分桶数据量过大:
    SELECT user_id, count(1) 
    FROM my_table_name 
    GROUP BY user_id 
    HAVING count(1) > 100000;
    
    若存在数据倾斜,调整分桶键为复合哈希键,分散热点数据:
    ALTER TABLE my_table_name SET DISTRIBUTED BY HASH(`user_id`, `city`) BUCKETS 18;
    
  • 切换聚合模型:如果查询以user_id分组聚合为主,可将UNIQUE KEY表改为AGGREGATE KEY表,预聚合count字段,减少查询计算量:
    CREATE TABLE IF NOT EXISTS my_table_agg
    (
        `user_id` LARGEINT NOT NULL COMMENT "用户id",
        `user_count` BIGINT COUNT DEFAULT "0" COMMENT "用户记录数",
        `date` DATE NOT NULL COMMENT "数据灌入日期时间"
    ) ENGINE = olap
    AGGREGATE KEY(`user_id`, `date`)
    PARTITION BY RANGE (`date`)
    (
      PARTITION `p201701` VALUES LESS THAN ("2017-02-01"),
      PARTITION `p201702` VALUES LESS THAN ("2017-03-01"),
      PARTITION `p201703` VALUES LESS THAN ("2017-04-01")
    )
    DISTRIBUTED BY HASH(`user_id`) BUCKETS 18
    PROPERTIES (
    "replication_allocation" = "tag.location.default: 1",
    "storage_medium" = "SSD",
    "replication_num" = "3"
    );
    

3. 集群配置优化

  • 调整BE内存参数:修改BE节点的be.conf配置,合理分配内存:
    • mem_limit = "56G":设置BE可用内存上限,预留8GB给系统进程
    • min_free_memory = "2G":提高系统最低可用内存阈值,避免触发内存保护机制
      修改后重启BE节点生效。
  • 启用查询队列:在FE的fe.conf中开启查询队列,限制并发查询总内存:
    enable_query_queue = true
    queue_max_memory_limit = "120G" -- 3BE节点总内存的60%左右
    
  • 限制并发查询数:在FE的fe.conf中设置max_concurrent_queries = 30,减少同时运行的查询数量,降低内存总负载。

4. 存储与数据量优化

  • 开启数据压缩:在表的PROPERTIES中添加压缩配置,减少内存加载的数据量:
    ALTER TABLE my_table_name SET ("compression" = "LZ4");
    
  • 检查数据量合理性:100GB数据在3BE节点上平均分配约33GB/节点,属于合理范围;若单分桶数据量超过10GB,继续增加分桶数至24或30。

内容的提问来源于stack exchange,提问作者Young

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 23:17:04