1. 项目概述
十年前我第一次接触Dremel时,就被它独特的列式存储和嵌套数据模型惊艳到了。当时我们团队正在处理PB级的日志分析,传统行存数据库在扫描效率上完全无法满足需求。Dremel的出现像一束光照进了数据处理的黑暗森林——它用列式存储+并行查询的组合拳,把我们的ETL作业从小时级降到了分钟级。
但真正让我着迷的是,这套架构思想后来催生了Parquet这样的开源列存格式。今天当我们在Spark、Presto这些MPP引擎里轻松使用Parquet时,很少有人知道这些技术血脉里流淌着Dremel的基因。这篇文章就带大家解剖这个演化历程,看看Google的论文如何通过"他山之石"塑造了现代MPP数据库的筋骨。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 核心技术解析
2.1 列式存储的革命性突破
传统行式存储(如MySQL)把整条记录连续存放,这在OLTP场景很高效。但当你要扫描十亿条记录却只需要其中两三个字段时,行存就成了性能杀手——磁盘必须读取所有字段数据,而I/O往往是分析查询的最大瓶颈。
Dremel的列存设计彻底改变了游戏规则。它将每个字段独立存储,查询时只需读取相关列的数据。我们做过实测:在相同压缩算法下,扫描100GB的日志数据,行存需要读取87GB数据,而列存仅需12GB。更妙的是,列存数据具有更好的局部性,现代CPU的SIMD指令集可以对其实现向量化计算。
实践提示:列存不是银弹。对于需要频繁访问整行数据的点查询(如主键查询),行存仍然更有优势。这就是为什么TiDB等HTAP系统会同时采用行存和列存引擎。
2.2 嵌套数据模型的优雅实现
处理JSON、Protocol Buffers这类嵌套数据时,传统方案要么将其序列化成BLOB(失去查询能力),要么平铺成多张表(导致复杂join)。Dremel提出的嵌套列存模型完美解决了这个问题——它通过"路径+重复/定义级别"的编码方式,在保持列存优势的同时原生支持嵌套结构。
举个例子,对于如下JSON记录:
json复制{
"user_id": "u123",
"events": [
{"time": "2023-01-01", "action": "click"},
{"time": "2023-01-02", "action": "purchase"}
]
