流式数据湖Paimon探秘之旅 (七) 读取流程全解析

第7章:读取流程全解析

读取的三个阶段

Paimon的读取分为三个阶段:

  1. 扫描计划(Scan):确定需要读取哪些文件
  2. 分片生成(Split):将文件分割成可并行处理的任务
  3. 数据读取(Read):从分片读取实际数据

深入每个阶段

7.1 FileStoreScan扫描接口

扫描的目的

从最新的Snapshot开始,找出所有需要读取的数据文件。

java 复制代码
FileStoreScan scan = fileStore.newScan();

// 应用谓词(where条件)
scan.withFilter(predicate);

// 获得读取计划
Plan plan = scan.plan();

// Plan包含:
// - 所有需要读的文件
// - 文件的元数据(min_key, max_key等)
扫描的性能优化

1. 谓词下推(Predicate Pushdown)

sql 复制代码
SELECT * FROM users WHERE age > 30;

不优化:
  读取: 所有users记录
  过滤: 哪些age > 30
  
优化后:
  检查Manifest:
    - file1: age min=20, max=28 → skip
    - file2: age min=25, max=35 → read ✓
    - file3: age min=30, max=40 → read ✓
  结果: 只读3个文件中的2个

2. 分区裁剪(Partition Pruning)

sql 复制代码
SELECT * FROM events WHERE dt='2024-01-15';

执行:
  读分区列表 → [dt=2024-01-01, dt=2024-01-15, dt=2024-01-31]
  过滤 → [dt=2024-01-15]
  只读dt=2024-01-15目录下的文件
  
效果: 扫描文件数减少 95%

7.2 Split生成与分发

什么是Split?

Split是数据文件的可读取单位,用于分布式读取。

ini 复制代码
原始文件:data-1.parquet (1GB)
        ↓
        Split1: offset=0, length=256MB
        Split2: offset=256MB, length=256MB
        Split3: offset=512MB, length=256MB
        Split4: offset=768MB, length=256MB
        ↓
        4个Split可以并行读取
Split的分配策略
perl 复制代码
单个并行度读取:
  Task-0: 读取所有splits顺序读取
  
多个并行度读取:
  Task-0: 读取 split-0, split-4, split-8, ...
  Task-1: 读取 split-1, split-5, split-9, ...
  Task-2: 读取 split-2, split-6, split-10, ...
  Task-3: 读取 split-3, split-7, split-11, ...
  
  (轮询分配splits)

7.3 SplitRead数据读取

读取的工作流程
java 复制代码
SplitRead<T> read = fileStore.newRead();

for (Split split : splits) {
  RecordReader reader = read.createReader(split);
  
  RecordBatch batch;
  while ((batch = reader.readBatch()) != null) {
    // 处理这批记录
    for (Record record : batch) {
      process(record);
    }
  }
  
  reader.close();
}
批量读取的好处
scss 复制代码
逐记录读取(低效):
  for i in 1..1000000 {
    record = file.read()  ← 1000000次I/O调用!
    process(record)
  }

批量读取(高效):
  for batch in batches {
    batch = file.readBatch(4096)  ← 仅245次I/O调用
    for record in batch {
      process(record)
    }
  }
  
性能提升: 4096倍!

7.4 谓词下推与过滤优化

三层过滤
yaml 复制代码
层1:Manifest级别过滤
  min_key <= target_key <= max_key?
  → 快速排除大量文件
  
层2:文件级别统计过滤
  file_stats:
    age: min=25, max=35
  age > 30?
  → 排除不符合的文件
  
层3:记录级别过滤
  (age > 30)? → keep : skip
  → 最终过滤
where子句的处理
sql 复制代码
WHERE user_id = 100 AND age > 30

分解为:
  谓词1: user_id = 100 (主键谓词 → Manifest过滤)
  谓词2: age > 30 (非主键谓词 → 记录级过滤)

执行:
  1. Manifest过滤 → user_id=100的bucket
  2. 读该bucket的文件
  3. 对每条记录检查 age > 30

总结:读取流程的关键优化

1. 多层过滤链

scss 复制代码
Manifest → 分区 → 文件统计 → 记录级
(快速)     (快速)  (中等)    (精准)

2. 批量处理

css 复制代码
减少I/O次数
减少虚拟机调用开销
提升CPU缓存命中率

3. 分布式并行

复制代码
Split分配 → 并行读取 → 吞吐量线性扩展

相关代码

  • FileStoreScan:paimon-core/src/main/java/org/apache/paimon/operation/FileStoreScan.java
  • SplitRead:paimon-core/src/main/java/org/apache/paimon/io/SplitRead.java
  • Split:paimon-api/src/main/java/org/apache/paimon/table/source/Split.java
相关推荐
wafrdggh5 小时前
2026电商快递批量查询怎么用?固乔助手模板设置评测
大数据·数据库·小程序
大大大大晴天7 小时前
OLTP、OLAP、数据湖、数据集市、湖仓一体到底是什么关系?
大数据
正在走向自律10 小时前
AI Agent 落地这一年:从“能跑起来”到“敢放出去”
大数据·人工智能·ai agent·智能体·mcp·a2a
freejackman11 小时前
【实战二】字段级血缘追踪:拆解 AST 迷局,精准穿透函数链与子查询
大数据·数据库·sql
goujunwe12 小时前
GEO 内容的“可摘录性”打磨技巧:段落、表格、小标题怎么写,方便大模型提取独立答案块
大数据·人工智能
小田学Python12 小时前
DeepSeek Harness 完整上手指南:安装部署 + 必装插件 + 用一周就回不去的功能
大数据·大模型·agent·ai工具·deepseek
成都蜀味缘餐饮技术培训学校16 小时前
手撕烤兔技术培训实战指南,秘制腌料配方比例与调制手法
大数据·经验分享·笔记·其他·微信公众平台
roman_日积跬步-终至千里16 小时前
AI 能让一个人成为团队吗?从数据中台到 OPC,重新理解软件工程能力
大数据·人工智能·软件工程
演艺大赏17 小时前
NiFi 数据流实战:FTP→HDFS 与 CSV→Parquet,附坏数据、漏文件与双写
大数据
数字新视界19 小时前
动环监控信创适配在智能机房管理中的应用价值与未来展望
大数据·服务器·数据库·动环监控系统·动力与环境监控系统