Fuse 引擎工作原理
Fuse 引擎
Fuse 引擎是 Databend 的核心存储引擎,专为在云对象存储上高效管理 PB 级数据而优化。默认情况下,在 Databend 中创建的表会自动使用此引擎(ENGINE=FUSE
)。受 Git 启发,其基于快照的设计支持强大的数据版本控制功能(如时间回溯(Time Travel)),并通过先进的剪枝和索引技术提供高查询性能。
本文档阐述其核心概念与工作原理。
核心概念
Fuse 引擎使用三个核心结构组织数据,设计灵感源自 Git:
- 快照(Snapshot,类似 Git 提交): 不可变引用,通过指向特定段(Segment)定义表在时间点的状态,支持时间回溯(Time Travel)。
- 段(Segment,类似 Git 树): 块(Block)的集合,包含用于快速数据跳过(剪枝)的汇总统计信息,可在快照间共享。
- 块(Block,类似 Git 对象): 不可变数据文件(Parquet 格式),存储实际行数据及详细的列级统计信息,用于细粒度剪枝。
表头(Table HEAD)
│
▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 段(SEGMENT A)│◄────│ 快照 2 │────►│ 段(SEGMENT B)│
│ │ │ 前一个: │ │ │
└───────┬───────┘ │ 快照 1 │ └───────┬───────┘
│ └───────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ 快照 1 │ │
│ │ │ │
│ └───────────────┘ │
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 块 1 │ │ 块 2 │
│ (cloud.txt) │ │(warehouse.txt)│
└───────────────┘ └───────────────┘
写入工作原理
向表添加数据时,Fuse 引擎会构建对象链。过程如下:
步骤 1:创建表
CREATE TABLE git(file VARCHAR, content VARCHAR);
此时表无数据:
(空表,无数据)
步骤 2:插入第一条数据
INSERT INTO git VALUES('cloud.txt', '2022/05/06, Databend, Cloud');
首次插入后,Fuse 引擎创建初始快照、段和块:
表头(Table HEAD)
│
▼
┌───────────────┐
│ 快照 1 │
│ │
└───────┬───────┘
│
▼
┌───────────────┐
│ 段 A │
│ │
└───────┬───────┘
│
▼
┌───────────────┐
│ 块 1 │
│ (cloud.txt) │
└───────────────┘
步骤 3:插入更多数据
INSERT INTO git VALUES('warehouse.txt', '2022/05/07, Databend, Warehouse');
插入新数据时,Fuse 引擎创建引用原始段和新段的新快照:
表头(Table HEAD)
│
▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 段 A │◄────│ 快照 2 │────►│ 段 B │
│ │ │ 前一个: │ │ │
└───────┬───────┘ │ 快照 1 │ └───────┬───────┘
│ └───────────────┘ │
│ │ │
│ ▼ │
│ ┌───────────────┐ │
│ │ 快照 1 │ │
│ │ │ │
│ └───────────────┘ │
│ │
▼ ▼
┌───────────────┐ ┌───────────────┐
│ 块 1 │ │ 块 2 │
│ (cloud.txt) │ │(warehouse.txt)│
└───────────────┘ └───────────────┘
读取工作原理
查询数据时,Fuse 引擎通过智能剪枝高效定位目标数据:
查询(Query):SELECT * FROM git WHERE file = 'cloud.txt';
表头(Table HEAD)
│
▼
┌───────────────┐ ┌───────────────┐ ┌───────────────┐
│ 段 A │◄────│ 快照 2 │────►│ 段 B │
│ 检查 │ │ │ │ 检查 │
└───────┬───────┘ └───────────────┘ └───────────────┘
│ ✗
│ (跳过 - 不包含
│ 'cloud.txt')
▼
┌───────────────┐
│ 块 1 │
│ 检查 │
└───────┬───────┘
│
│ ✓ (包含 'cloud.txt')
▼
读取此块
智能剪枝过程
┌─────────────────────────────────────────┐
│ 查询(Query):WHERE file = 'cloud.txt' │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 检查段 A │
│ 最小文件值:'cloud.txt' │
│ 最大文件值:'cloud.txt' │
│ │
│ 结果:✓ 可能包含 'cloud.txt' │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 检查段 B │
│ 最小文件值:'warehouse.txt' │
│ 最大文件值:'warehouse.txt' │
│ │
│ 结果:✗ 不可能包含 'cloud.txt' │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 检查段 A 中的块 1 │
│ 最小文件值:'cloud.txt' │
│ 最大文件值:'cloud.txt' │
│ │
│ 结果:✓ 包含 'cloud.txt' │
└─────────────────┬───────────────────────┘
│
▼
┌─────────────────────────────────────────┐
│ 仅读取块 1 │
└─────────────────────────────────────────┘
基于快照的功能
Fuse 引擎的快照架构支持以下高级数据管理能力:
时间回溯(Time Travel)
查询任意历史时间点的数据状态,支持数据分支、标记和治理,并提供完整审计跟踪与错误恢复。
零拷贝模式演进
无需重写底层数据文件即可修改表结构(添加列、删除列、重命名、更改类型)。
- 变更仅为元数据操作,记录于新快照中。
- 操作瞬时完成,无需停机,避免高成本数据迁移,旧数据仍可通过原始模式访问。
查询加速的高级索引(Fuse 引擎)
除基于统计信息的块/段剪枝外,Fuse 引擎提供专用二级索引以加速特定查询模式:
索引类型 | 简要描述 | 加速查询类型 | 示例查询片段 |
---|---|---|---|
聚合索引(Aggregate Index) | 为指定分组预计算聚合结果 | 加速 COUNT 、SUM 、AVG ... + GROUP BY | SELECT COUNT(*)... GROUP BY city |
全文索引(Full-Text Index) | 支持文本内关键词快速检索的倒排索引 | 使用 MATCH 的文本搜索(如日志分析) | WHERE MATCH(log_entry, 'error') |
JSON 索引(JSON Index) | 索引 JSON 文档内特定路径/键 | 针对 JSON 路径/值的过滤 | WHERE event_data:user.id = 123 |
布隆过滤器索引(Bloom Filter Index) | 通过概率检查快速跳过不匹配块 | 点查找(= )及 IN 列表过滤 | WHERE user_id = 'xyz' |
对比:Databend Fuse 引擎 vs. Apache Iceberg
注意: 本对比聚焦表格式功能。作为 Databend 原生表格式,Fuse 持续演进以提升可用性与性能。功能基于当前版本,未来可能变更。
功能 | Apache Iceberg | Databend Fuse 引擎 |
---|---|---|
元数据结构 | 清单列表 -> 清单文件 -> 数据文件 | 快照(Snapshot) -> 段(Segment)-> 块(Block) |
统计级别 | 文件级(+分区(Partition)) | 多级(快照、段、块)→ 更精细剪枝 |
剪枝能力 | 良好(文件/分区统计) | 优秀(多级统计 + 二级索引) |
模式演进 | 支持(元数据更改) | 零拷贝(仅元数据,瞬时) |
数据聚簇 | 排序(写入时) | 自动优化(后台) |
流式支持 | 基本流式摄取 | 高级增量(插入/更新跟踪) |