列式 vs 行式存储¶
Explanation · 原理入门
一句话理解
行式把一行所有字段连着存 —— 适合"读整行"的 OLTP;列式把一列所有值连着存 —— 适合"扫很多行但只取少数列"的 OLAP 与 AI 数据准备。湖仓 99% 选列式。
结构差异¶
给一张表 (id, name, age, city),三行数据:
行式存储:
列式存储:
一个是"行粒度连续",一个是"列粒度连续"。
为什么列式适合分析¶
- 列剪裁(column pruning) —— 查询
SELECT avg(age)只读age这一列,完全不碰其他 - 压缩比高 —— 同列值类型一致、重复多,字典 / RLE / bit-packing 效果极好;行式做不到
- 向量化执行友好 —— 一列连续存放 = SIMD 批处理的天然输入
- 谓词下推 + 统计 —— 每个 Row Group / Block 存 min/max/bloom,查询可以跳过大片数据
典型 10 倍以上的分析吞吐差距,都来自这四件事。
为什么行式适合事务¶
- 写一行 = 一次 IO —— 列式要写 N 次(每列一次)
- 点查读整行方便 —— 列式要拼回 N 列
- 行锁 / MVCC 简单 —— 行是最小管理单位
所以 OLTP(MySQL InnoDB、dstore)全用行式,OLAP / 湖仓 / AI 训练数据全用列式。
混合派:PAX / Row Group¶
两个世界中间有一条路叫 PAX / Row Group:把一批行(例如 128MB)作为一个"块",块内按列存。这是 Parquet / ORC / Lance 共用的思路:
- 块内列式 → 批量分析快
- 块仍以"批行"为单位 → IO 粒度可控
这基本等于"列式的 99%,但对大块批写更友好"。
湖仓里的含义¶
湖表层面你看到的 Parquet / ORC / Lance 都是列式的(更准确说是 PAX 列式)。 这决定了你在湖上最好的两件事:
- OLAP 分析 —— 列式天然加成
- AI 数据准备 / 训练集 —— 批扫 + 列剪裁是典型访问模式
最坏的事:高频行级点查。这种负载要么离开湖(走 DB),要么在湖上加一层加速(ClickHouse / StarRocks 作为物化层)。
相关概念¶
- Parquet、Lance Format —— 主流列式实现
- 向量化执行 —— 列式的直接受益者
延伸阅读¶
- Column-Stores vs. Row-Stores: How Different Are They Really? (Abadi et al., SIGMOD 2008)
- Weaving Relations for Cache Performance (PAX paper, VLDB 2001)