前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >为什么列式存储更适合OLAP?

为什么列式存储更适合OLAP?

作者头像
闫同学
发布2025-03-07 15:38:10
发布2025-03-07 15:38:10
7500
代码可运行
举报
文章被收录于专栏:扯编程的淡扯编程的淡
运行总次数:0
代码可运行

列式存储是一种数据存储方式,其核心思想是将数据按列而非按行进行组织和存储。它与传统的行式存储在数据布局、适用场景和性能特征上有显著差异。

Clickhouse等OLAP数据存储系统正是由于其使用列式存储,很大程度的提高了数据查询和分析能力,这篇文章我就向大家分享一下行式存储和列式存储到底有何区别?为什么Clickhouse等OLAP系统更偏向使用列式存储?

先说一下基本概念

行式存储列式存储是两种不同的数据存储方式。注意是底层的存储方式不同,对于我们上层使用而言都是差不多的表结构。

行式存储将每一行的数据连续存储在一起,适合事务处理,可以快速读取整条记录;而列式存储将每一列的数据连续存储在一起,适合数据分析,查询特定列时只需读取该列数据,压缩效率更高。

简单来说,行式存储适合频繁的增删改查操作,列式存储则更适合大数据分析和聚合查询。

举例

行式存储(Row-Based),按行连续存储:

代码语言:javascript
代码运行次数:0
复制
| 用户ID | 姓名  | 年龄 | 地址 |
| ------ | ----- | ---- | ---- |
| 1      | Alice | 25   | 北京 |
| 2      | Bob   | 30   | 上海 |
| 3      | Carol | 28   | 深圳 |

磁盘存储结构(假设每行连续存放):

代码语言:javascript
代码运行次数:0
复制
1,Alice,25,北京 | 2,Bob,30,上海 | 3,Carol,28,深圳

列式存储(Column-Based),列式存储示例(按列独立存储):

代码语言:javascript
代码运行次数:0
复制
用户ID列 → [1, 2, 3]
姓名列   → [Alice, Bob, Carol]
年龄列   → [25, 30, 28]
地址列   → [北京, 上海, 深圳]

磁盘存储结构(每列独立存储为文件):

代码语言:javascript
代码运行次数:0
复制
用户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过程:

代码语言:javascript
代码运行次数:0
复制
需要读取所有行的完整数据(包括无关字段):
1,Alice,25,北京 → 提取25
2,Bob,30,上海   → 提取30
3,Carol,28,深圳 → 提取28

总读取数据量为3行 × 4列 = 12个字段,有效数据占比为25%

列式存储的I/O过程:

代码语言:javascript
代码运行次数:0
复制
仅读取年龄列文件(年龄.bin → [25, 30, 28]):
直接获取所有年龄值,无需处理其他字段。

总读取数据量为3行 × 1列 = 3个字段,有效数据占比为100%

3)数据压缩

行式存储:单行内不同列的数据类型差异大(如字符串、数值混杂),压缩率低。

列式存储:单列数据具有相同类型和语义,可通过 高效压缩算法(如LZ4、ZSTD、Delta编码)大幅降低存储空间(通常压缩比可达5-10倍),同时减少磁盘到内存的数据传输量。

4)CPU计算优化

针对列式存储而言,现代CPU支持单指令多数据流(SIMD),可对连续的同类型列数据批量计算(如一次处理128个数值),显著提升聚合计算速度。其次,连续存储的列数据更易被CPU缓存命中,减少内存访问延迟。

ClickHouse为何选择列式存储?

ClickHouse专为OLAP场景设计,其核心需求是 高速处理海量数据的聚合查询,而列式存储的以下特性完美契合这一目标:

减少数据扫描量:OLAP查询通常仅涉及少数列(如统计某几列的SUM/AVG)。列式存储仅需读取相关列,避免加载无关数据。

最大化压缩效率:高压缩率不仅节省存储成本,还减少磁盘到内存的数据传输时间,提升查询吞吐量。

向量化执行引擎:ClickHouse的查询引擎针对列式数据设计,可批量处理列数据,利用SIMD指令加速计算。

预聚合与索引优化:列式存储便于实现稀疏索引、跳数索引(如GRANULARITY),快速定位数据块,减少扫描范围。

场景对比

操作

行式存储

列式存储

单行读写(如INSERT)

快(顺序写)

慢(需更新多列文件)

全表扫描(如COUNT)

快(仅读一列)

聚合查询(如SUM)

慢(读所有行)

快(仅读一列)

压缩率

小总结

列式存储通过按列组织数据、减少I/O、高效压缩和向量化计算,在OLAP场景中实现了比行式存储高1-2个数量级的查询性能。ClickHouse等OLAP系统正是基于这些原理,选择列式存储作为其高性能分析引擎的核心基础,使其在海量数据实时分析领域表现出色。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-03-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 扯编程的淡 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 先说一下基本概念
  • 列式存储与行式存储的核心差异
  • ClickHouse为何选择列式存储?
  • 场景对比
  • 小总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档