查询外部glue hive后fe宕机

Viewed 11

环境

  • doris版本: doris-3.0.6.2-rc01
  • selectdb版本: v25.1.1

背景

由于业务需要, 需要在doris中查询aws的athena数据, 而athena的metadata存放于aws的glue, 因此参考doris官方文档, 创建外部catalog读取数据, 文档地址: https://doris.apache.org/zh-CN/docs/3.x/lakehouse/metastores/aws-glue?_highlight=glue#hive-glue-catalog

现象

  • 开始使用的时候查询分区较少的表的时候, 能够正常出结果, 但是如果查询分区多的表时, fe便会出现内存/cpu拉满, 导致新会话无法连接, 服务器无响应(将分区的值写入到 where 中也无法解决这个问题).
    • 正常现象, 查询的表分区约为 1000+
      image.png
      cpu和内存在短暂的飙高之后稳定下来
    • 异常现象, 查询的表分区数目粗略估计为58w个
      image.png
      cpu和内存拉升之后, 未能降下来, 且发起的sql卡死

分析

  • 结合AI以及查看源码发现, doris会在事务发起的时候, 全量拉取所有分区的.

期望

  • doris在分析sql生成执行计划的时候, 能够将where中跟分区有关的条件下沉到分区的查找中, 避免全量拉取所有分区的产生的fe宕机现象
1 Answers

AI解答:

在做查询绑定/分区裁剪时,Doris 会调用 HiveMetaStoreCache.getPartitionValues(...) 来获得表的所有分区值(用于 planner 做分区裁剪)。看代码:

HiveMetaStoreCache.loadPartitionValues 调用: catalog.getClient().listPartitionNames(nameMapping.getRemoteDbName(), nameMapping.getRemoteTblName()); (见 HiveMetaStoreCache.java loadPartitionValues,约 line ~240)
注意这里没有传 any partition values 或表达式 —— 所以 catalog client 被要求“列出该表的所有分区名”。
catalog client(AWSCatalogMetastoreClient -> GlueMetastoreClientDelegate)行为:

GlueMetastoreClientDelegate.listPartitionNames 接受一个 List values 参数并在有值时会把它转换为 Glue 的 expression(ExpressionHelper.buildExpressionFromPartialSpecification),再调用 getPartitions(...)。但这个分支只有当上层传入 values 时才会走(见 GlueMetastoreClientDelegate.listPartitionNames,约 line ~771-789)。
但上一步 HiveMetaStoreCache 是用无参 listPartitionNames() 调用的,因此 expression = null,最终调用 DefaultAWSGlueMetastore.getPartitions(..., expression=null, max),导致会分页/并(取决于 max)最终把所有分区拉到内存。
DefaultAWSGlueMetastore 的实现会在 max < 0 或 max > 1000 时走并行分段并最终把每个 segment 的全部分页结果拼成一个 List 并返回(见 DefaultAWSGlueMetastore.getPartitions / getPartitionsParallel / getCatalogPartitions)。也就是说一旦触发“无过滤”“要全部分区”的请求,Glue 会把大量数据分段/分页返回,FE 会把这些 Partition 对象收集到内存并转换为 String 名称 —— 导致内存/CPU/线程压力。

为什么你的 WHERE 没生效(两种可能)

根因 A(最主要):Doris 当前调用分区元数据的入口(partitionValuesCache 的加载)没有把 SQL 的分区谓词作为参数传给 listPartitionNames;因此不管查询写没写分区条件,cache 首次加载都会拉全量分区。
根因 B(次要/存在条件):即便某处尝试把谓词转换成 Glue expression(ExpressionHelper 能做到这一点),只有在上层确实把 partition values 传入 listPartitionNames 的情况下才会被使用;而当前缓存加载路径没有这样做。
补充:ExpressionHelper 的作用

ExpressionHelper.buildExpressionFromPartialSpecification 能把部分分区值(按前缀顺序)拼成 Glue 可识别的表达式(例如 (biz_dt='20251221') AND (cmd='xxx')),并做些类型/引号修正;但是该逻辑只在 GlueMetastoreClientDelegate.listPartitionNames 接收到非空 values 时被触发(见 ExpressionHelper.java)。