流式数据湖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
相关推荐
中电金信6 分钟前
中电金信参编的团体标准《商业银行应用程序接口治理能力要求》正式发布
大数据·运维·人工智能
SelectDB27 分钟前
1TB/天 × 30 天日志成本怎么估:核对命令、降冷配置与踩坑记录
大数据·数据库·数据分析
SelectDB30 分钟前
日志选型别只比 Loki 和 ELK:三条路径、一份可复制的落地清单
大数据·数据库·数据分析
SelectDB33 分钟前
ES 写入拒绝与磁盘暴涨:排查命令、参数调整与改用 Doris 的落地步骤
大数据·数据库·数据分析
RPAdaren38 分钟前
AI 舆情智能体频繁断跑、漏抓发酵?90% 团队都踩了同一层坑
大数据·人工智能
Data-Miner1 小时前
怎么批量处理Excel文件?一段月底对账剧本讲明白
大数据
千里码aicood1 小时前
基于Hadoop的机票价格波动分析系统的设计与实现
大数据·hadoop·分布式
無a伟1 小时前
彻底搞懂ToolCalling、MCP,Skills的核心区别,能力上的层层封装
大数据·agent·mcp·toolcalling·skills
xbgRS2 小时前
Elasticsearch的分词器
大数据·elasticsearch·搜索引擎
Geeys2 小时前
拼多多店铺怎么运营才能有订单?新手低成本出单攻略
大数据·网络·人工智能