土法炼钢兴趣小组的算法知识备份

【分布式 OLAP 查询引擎】内存、Spill 与资源隔离

文章导航

分类入口
databasedistributed
标签入口
#trino#memory-management#spill#resource-groups#revocable-memory#hash-join#aggregation#olap

目录

第 9 篇 在算子层讲过 hash join 的 build 表与 partial/final aggregation;第 11 篇 讲过 Exchange 缓冲 Page。生产里更常遇到的是:查询还没算完,Coordinator 报 Exceeded memory limit、个别 Worker spill 到盘却更慢、多租户抢内存导致全员排队——这些属于 集群级内存治理,不是单算子代码能单独解释的。

本文是系列 第 16 篇,建立 Trino 主线上的 内存账户 → spill → resource group 心智模型,并和 stream-processing 第 18 篇背压 对照:流式背压 限的是管道 buffer 与 checkpoint;交互式 OLAP 限的是 查询峰值内存与 revocable 回收

环境说明:本机 未部署 Trino 集群,正文机制来自 Trino 476+ 官方文档 Memory managementSpillResource groups(A 级)。不粘贴未实测的 spill 字节数或 EXPLAIN ANALYZE 内存字段。DuckDB 单进程内存行为见 第 14 篇 边界一句。


一、为什么 OLAP 内存是「账户制」

OLTP(postgresql-kernel)单查询内存通常由 work_mem 等参数封顶,超出可能 sort/hash 落盘或直接失败。分布式 OLAP 额外有:

Trino 用 分层 memory pool + query context 跟踪:GENERAL 池、RESERVED、以及 per-query 的 user memory / revocable memory 计数(文档术语,具体类名见源码 ClusterMemoryManager)。

flowchart TB
  CLUSTER["Cluster memory limit"] --> POOL["General pool"]
  POOL --> Q1["Query A context"]
  POOL --> Q2["Query B context"]
  Q1 --> OP["Operators<br/>hash / agg / exchange"]
  OP -->|pressure| SPILL["Local spill files"]
  POOL -->|exceeded| KILL["Query failure / OOM"]

二、Query / User / Cluster 限额

Trino 配置层常见限额(config.properties / session,文档 Properties):

层级 典型属性 作用
Cluster query.max-memory 单查询在所有节点 user memory 之和上限
query.max-total-memory 含 revocable 在内的总量上限
Node memory.heap-headroom-per-node 留给 OS/GC 的头寸,防节点 OOM
Session query_max_memory 覆盖单 session 查询上限

user memory 近似「算子已分配且短期不会还给池子」的部分;revocable可被 spill 回收 的部分(hash table、部分 agg 状态)。Exchange 缓冲、某些 pipeline 缓冲属于 non-revocable 或单独记账——这就是为什么「query 看起来没跑 join 仍 OOM」:可能是 shuffle 缓冲 + broadcast 表 占满。

第 5 篇 联动:broadcast join 把小表复制到每个 Worker,user memory 按 Worker 数放大;估错行数时 broadcast 误判是生产 OOM 主因之一。


三、Spill:哪些算子、什么路径

Trino 文档 Spill(A 级)说明下列算子可在内存压力下 写本地磁盘(格式为引擎内部二进制,非 Parquet):

算子 Spill 内容 触发直觉
Hash Join Build 侧 partition 落盘,probe 多次回放 大 build 表
Hash Aggregation 分组状态 partition 高基数 GROUP BY
Order By 排序 run 外排 大结果集排序
Window 部分场景 partition 缓冲 大窗口帧

流程概要:

  1. Memory pool 达到 revocable 回收阈值
  2. Operator 收到 spill 信号,将 部分 hash partition 序列化到 spill 目录(spiller-spill-path 等配置)。
  3. 继续处理剩余内存内 partition;probe 阶段 读回 spill 完成 join。

代价:磁盘 IO 与多次 probe 使 wall time 陡增;EXPLAIN ANALYZE 中可见 Spilled 相关指标(文档 Explain analyze;本机未实测数值)。Spill 不保证 一定避免失败——若 spill 速度跟不上分配速度,或 disk 满,仍 Exceeded memory limit

第 9 篇 实验设计:调低 query.max-memory 构造大 join,观察 plan 是否出现 spill——需在 Docker Trino 栈执行(reproduce/docker-compose.yml),本篇不伪造输出。


四、Resource Group:并发与隔离

Resource group(Trino docs, Resource groups,A 级)在 Coordinator 做 多租户队列

机制 说明
Hard concurrency limit 组内同时运行查询数上限
Soft limit + queue 超出进入队列,按优先级出队
Per-group memory limit 组内查询共享内存预算
Selector 按 user、source、query type 路由到组

典型划分:交互式 BI(低并发、短查询、紧 memory limit) vs ETL 批查询(高并发、长查询、独立组)。与 Spark Fair Scheduler pool 类似,但 Trino 在 Coordinator 单点 决策,Worker 只执行已批准 query。

Hard concurrency limit = 0 可维护模式拒绝新查询;soft limit 过高会导致 内存求和仍超 cluster,触发全局 kill。


五、与流式背压的对照

stream-processing/18 的 Flink credit-based 背压 解决 有界 buffer 下生产者别压垮消费者:下游慢 → credit 不释放 → 上游停读。

维度 流式(Flink) 交互式 OLAP(Trino)
控制对象 Subtask 间 record 流 Query 内存账户 + 线程池
反压信号 Input gate credit Memory pool 压力、队列
缓冲突出 状态后端 + checkpoint Spill 文件
隔离单元 作业 / 算子链 Resource group / query
用户感知 Lag、checkpoint 超时 排队、query killed

OLAP 通常无全局 backpressure 协议:慢查询占满 Worker 线程与内存,靠 resource group + kill policy 隔离,而不是逐 Page 反压上游 scan(scan 仍可能全速读直到 memory 触顶)。这是 第 1 篇 交互式 vs 流式 边界在生产资源层的体现。


六、Spark 与 DuckDB 边界(对照一句)


七、运维检查清单

  1. Kill 前看 query.max-memory vs 实际 broadcast 表大小 × worker 数
  2. Spill 目录 磁盘空间与本地 SSD;HDD spill 易成 straggler(第 17 篇)。
  3. Resource group 是否把重 ETL 与 BI 混在同一 general pool
  4. Revocable 比例:大 join + 大 agg 同 query 时 spill 顺序与重复读盘。
  5. Node OOM:区分 JVM heap OOM(调 heap、headroom)与 query limit(调 plan 或 SQL)。

八、小结


上一篇Iceberg 下推全链路

下一篇经典故障与排查

返回 系列目录


参考资料

  1. Trino Documentation 476+, Memory management / Spill / Resource groups / Properties(A 级)。
  2. Trino Documentation, Explain analyze(A 级;字段说明,无本机数值)。
  3. stream-processing/18 背压(B 级对照)。
  4. DuckDB Documentation, Memory Management(A 级;嵌入式边界)。

同主题继续阅读

把当前热点继续串成多页阅读,而不是停在单篇消费。

2026-07-07 · database / distributed

【分布式 OLAP 查询引擎】Join 重排与物理算子选择

Join order enumeration、Hash/Merge/Nested Loop 适用条件;Trino broadcast vs partitioned join 与 shuffle 网络代价;Dynamic partition pruning 与 runtime filter;DuckDB HASH_JOIN 实测与 Spark AQE 对照边界。

2026-07-07 · database / distributed

【分布式 OLAP 查询引擎】引擎选型与数据平台阅读地图

用决策树收束 Trino/Spark/ClickHouse/DuckDB/DataFusion/PostgreSQL 的适用边界:交互式联邦、批 ETL、嵌入式分析、流批一体各走哪条路径;给出能力对照表(无吞吐排名)与 postgresql→columnar→lakehouse→stream→query-engine 全栈阅读顺序,闭合数据平台栈。


By .