两种存储布局的区别
行式存储把一行的所有列连续放在一起,读一行就要读一次连续段,因此点查与单行更新很快。列式存储把同一列的数据连续存放,分析型查询只读少数几列时,IO 量能按列裁剪,压缩率也更高——因为同一列数据类型相同、取值相近。两者不是谁替代谁,而是面向不同访问模式:事务系统多用行存,分析系统多用列存。
对比
| 维度 | 行式存储 | 列式存储 |
|---|---|---|
| 读取模式 | 整行读取,点查友好 | 按列读取,扫描少数列划算 |
| 压缩效率 | 同行列类型混杂,压缩率一般 | 同列同类型,压缩率高 |
| 写入模式 | 追加与更新都方便 | 批量写入友好,单行更新代价高 |
| 典型场景 | OLTP 事务、单行更新 | OLAP 分析、宽表扫描 |
| 代表实现 | MySQL InnoDB、PostgreSQL 堆表 | Parquet、ORC、ClickHouse 列存 |
基本信息
| 列存文件结构 | 行组(row group)内按列分块,附统计信息 |
|---|---|
| 裁剪手段 | 分区裁剪、行组统计跳过、列裁剪 |
| 编码优化 | 字典编码、游程编码,对有序数据效果显著 |
| 向量化 | 按列批量处理,配合现代 CPU 的批处理指令 |
| 选型要点 | 先看访问模式:点查多还是扫描多 |
同一份数据的两种读法
同一份数据的两种读法
查询:SELECT SUM(amount) FROM orders WHERE dt='2026-10-11'
行式:读出该分区所有行的全部列,再丢弃用不到的列
列式:只读 amount 与 dt 两列的数据块,其余列完全不解码
结论:列式扫描数据量可能只有行式的十分之一典型使用场景
- 业务库选择行存:订单创建、单条更新、按主键查询
- 数仓与湖上选择列存:大范围聚合、宽表扫描、指标计算
- 混合负载:用行库承接事务,定期同步到列存供分析
- 需要频繁 upsert 的湖表:依靠表格式的写入机制弥补列存更新代价
- 读多写少的归档数据:列存压缩后长期保存成本更低
数据湖/数仓以列存为主,但需要频繁按行更新的场景仍需行存或支持 upsert 的表格式。
列存的压缩收益与「同列取值相近」高度相关:按时间分区并排序写入后,压缩率通常明显优于随机插入。