列式存储是一种数据存储方式,其核心思想是将数据按列而非按行进行组织和存储。它与传统的行式存储在数据布局、适用场景和性能特征上有显著差异。
Clickhouse等OLAP数据存储系统正是由于其使用列式存储,很大程度的提高了数据查询和分析能力,这篇文章我就向大家分享一下行式存储和列式存储到底有何区别?为什么Clickhouse等OLAP系统更偏向使用列式存储?
行式存储和列式存储是两种不同的数据存储方式。注意是底层的存储方式不同,对于我们上层使用而言都是差不多的表结构。
行式存储将每一行的数据连续存储在一起,适合事务处理,可以快速读取整条记录;而列式存储将每一列的数据连续存储在一起,适合数据分析,查询特定列时只需读取该列数据,压缩效率更高。
简单来说,行式存储适合频繁的增删改查操作,列式存储则更适合大数据分析和聚合查询。
举例:
行式存储(Row-Based),按行连续存储:
| 用户ID | 姓名 | 年龄 | 地址 |
| ------ | ----- | ---- | ---- |
| 1 | Alice | 25 | 北京 |
| 2 | Bob | 30 | 上海 |
| 3 | Carol | 28 | 深圳 |
磁盘存储结构(假设每行连续存放):
1,Alice,25,北京 | 2,Bob,30,上海 | 3,Carol,28,深圳
列式存储(Column-Based),列式存储示例(按列独立存储):
用户ID列 → [1, 2, 3]
姓名列 → [Alice, Bob, Carol]
年龄列 → [25, 30, 28]
地址列 → [北京, 上海, 深圳]
磁盘存储结构(每列独立存储为文件):
用户ID.bin → 1,2,3
姓名.bin → Alice,Bob,Carol
年龄.bin → 25,30,28
地址.bin → 北京,上海,深圳
画个图可能更清楚一些:
1)数据组织方式
行式存储:数据按行连续存储。例如,表中一行数据的所有字段(如 用户ID、姓名、年龄、地址
)在磁盘上连续存放,形成一个数据块。适用场景:事务型处理(OLTP),如频繁的单行读写、点查询。
列式存储:数据按列连续存储。例如,所有用户的 用户ID
存储在一起,所有 年龄
存储在一起,形成多个独立的列数据块。适用场景:分析型处理(OLAP),如聚合统计、批量扫描。
2)I/O效率
行式存储:读取单行数据时效率高,但若需统计某列的聚合值(如 SUM(年龄)
),需要读取整行数据(包含无关字段),导致 I/O放大。
列式存储:仅读取目标列的数据,显著 减少I/O量。例如统计 年龄总和
时,只需读取 年龄
这一列。
举例:
行式存储的I/O过程:
需要读取所有行的完整数据(包括无关字段):
1,Alice,25,北京 → 提取25
2,Bob,30,上海 → 提取30
3,Carol,28,深圳 → 提取28
总读取数据量为3行 × 4列 = 12个字段
,有效数据占比为25%
列式存储的I/O过程:
仅读取年龄列文件(年龄.bin → [25, 30, 28]):
直接获取所有年龄值,无需处理其他字段。
总读取数据量为3行 × 1列 = 3个字段,有效数据占比为100%
3)数据压缩
行式存储:单行内不同列的数据类型差异大(如字符串、数值混杂),压缩率低。
列式存储:单列数据具有相同类型和语义,可通过 高效压缩算法(如LZ4、ZSTD、Delta编码)大幅降低存储空间(通常压缩比可达5-10倍),同时减少磁盘到内存的数据传输量。
4)CPU计算优化
针对列式存储而言,现代CPU支持单指令多数据流(SIMD),可对连续的同类型列数据批量计算(如一次处理128个数值),显著提升聚合计算速度。其次,连续存储的列数据更易被CPU缓存命中,减少内存访问延迟。
ClickHouse专为OLAP场景设计,其核心需求是 高速处理海量数据的聚合查询,而列式存储的以下特性完美契合这一目标:
减少数据扫描量:OLAP查询通常仅涉及少数列(如统计某几列的SUM/AVG)。列式存储仅需读取相关列,避免加载无关数据。
最大化压缩效率:高压缩率不仅节省存储成本,还减少磁盘到内存的数据传输时间,提升查询吞吐量。
向量化执行引擎:ClickHouse的查询引擎针对列式数据设计,可批量处理列数据,利用SIMD指令加速计算。
预聚合与索引优化:列式存储便于实现稀疏索引、跳数索引(如GRANULARITY
),快速定位数据块,减少扫描范围。
操作 | 行式存储 | 列式存储 |
---|---|---|
单行读写(如INSERT) | 快(顺序写) | 慢(需更新多列文件) |
全表扫描(如COUNT) | 慢 | 快(仅读一列) |
聚合查询(如SUM) | 慢(读所有行) | 快(仅读一列) |
压缩率 | 低 | 高 |
列式存储通过按列组织数据、减少I/O、高效压缩和向量化计算,在OLAP场景中实现了比行式存储高1-2个数量级的查询性能。ClickHouse等OLAP系统正是基于这些原理,选择列式存储作为其高性能分析引擎的核心基础,使其在海量数据实时分析领域表现出色。