570 字
2 分钟
为什么 OLAP 需要列式存储
OLAP(Online Analytical Processing)数据库是专门用于数据分析的数据库,如 ClickHouse、Apache Druid、Redshift 等。这类数据库几乎都使用列式存储。为什么?
一、行式存储 vs 列式存储
1.1 行式存储
flowchart LR
subgraph 行式存储
R1[id:1, name:张三, age:28, salary:10000]
R2[id:2, name:李四, age:35, salary:20000]
end
Note: 连续存储整行数据
1.2 列式存储
flowchart LR
subgraph 列式存储
C1[id:1,2]
C2[name:张三,李四]
C3[age:28,35]
C4[salary:10000,20000]
end
Note: 每列单独存储
二、OLAP 查询的特点
2.1 典型 OLAP 查询
-- OLAP 典型查询:聚合分析SELECT date_trunc('month', order_date) as month, category, SUM(amount) as total_amount, AVG(amount) as avg_amount, COUNT(*) as order_countFROM ordersWHERE region = '华东'GROUP BY 1, 2HAVING SUM(amount) > 100000ORDER BY 1, 4 DESCLIMIT 100;2.2 查询特征
| 特征 | OLAP | OLTP |
|---|---|---|
| 查询类型 | 聚合、聚合、再聚合 | 单条读写 |
| 扫描范围 | 大量行,少量列 | 少量行,全部列 |
| 并发 | 低并发,大查询 | 高并发,小查询 |
| 延迟 | 允许秒级 | 必须毫秒级 |
三、列式存储的优势
3.1 列式存储的读取优势
flowchart LR
subgraph 查询: SELECT AVG(salary) FROM employees
R[扫描所有 salary 列]
end
subgraph 行式存储
A[读取整行 → 丢弃不需要的列]
Note: 浪费 I/O
end
subgraph 列式存储
B[只读取 salary 列]
Note: 只读需要的列
end
I/O 节省:
- 行式存储:读取 100 列 × 1,000,000 行
- 列式存储:只读取 1 列 × 1,000,000 行
- 节省 99% I/O
3.2 压缩效率
flowchart LR
subgraph 列式存储更容易压缩
C1[国家: CN,CN,CN,US,US,JP...]
Note: 相同值连续出现
C2[列式压缩后: CNx3, USx2, JPx1]
end
| 压缩技术 | 适用场景 |
|---|---|
| Dictionary | 低基数列(国家、性别) |
| Run-Length | 重复值多的列 |
| Delta | 有序数列(时间戳、ID) |
| Bit-Packing | 布尔值、小整数 |
3.3 向量化执行
# 列式存储支持向量化执行# 一次处理多个值(SIMD)
# 伪代码:计算 AVGvalues = column_reader.read('salary', 1024) # 一次读 1024 个值sum = simd_sum(values) # SIMD 指令并行求和count = 1024avg = sum / count四、ClickHouse 的列式存储实践
4.1 MergeTree 存储结构
flowchart TB
subgraph MergeTree
P[PARTITION BY]
S[SORT BY]
M[Mark Ranges]
end
subgraph 数据存储
P1[part_1]
P2[part_2]
P3[part_3]
end
4.2 列式存储的性能数据
# ClickHouse 性能测试# 1 亿行数据,聚合查询
# 行式存储 (MySQL): ~5 秒# 列式存储 (ClickHouse): ~0.05 秒# 性能提升: 100 倍五、行式存储仍然有用的场景
5.1 OLTP 场景
| 场景 | 推荐 |
|---|---|
| 事务处理 | 行式存储 |
| 点查询(主键) | 行式存储 |
| 更新频繁 | 行式存储 |
| 少量行读取 | 行式存储 |
5.2 HTAP 混合场景
现代数据库通过行列混合来平衡:
-- 创建行列混合表CREATE TABLE orders ( id UInt64, customer_id UInt64, order_date Date, amount Decimal(10,2)) ENGINE = MergeTree()ORDER BY (customer_id, order_date)SETTINGS storage_policy = 'hybrid';六、总结
6.1 OLAP 为什么需要列式存储?
| 原因 | 说明 |
|---|---|
| I/O 高效 | 只读取需要的列 |
| 压缩更好 | 同列数据相似,压缩率高 |
| 向量化 | 支持 SIMD 并行处理 |
| 聚合友好 | 列聚合无需读取整行 |
6.2 列式 vs 行式
| 特性 | 列式存储 | 行式存储 |
|---|---|---|
| 查询模式 | 少量列,大量行 | 全部列,少量行 |
| 压缩率 | 高 | 低 |
| 写入性能 | 低 | 高 |
| 点查询 | 差 | 好 |
| 聚合查询 | 好 | 差 |
核心观点:不同的查询模式适合不同的存储格式。OLAP 的分析型查询天然适合列式存储,而 OLTP 的事务型场景仍需要行式存储。
参考资料
- ClickHouse Documentation — 列式数据库
- [Column-Oriented Storage](https://clickhouse.com/docs/en/guides/our-niños storage/) — 存储原理
支持与分享
如果这篇文章对你有帮助,欢迎支持作者或分享给更多人
部分信息可能已经过时
相关文章 智能推荐
1
为什么数据库会丢失数据
技术科普 深入解析数据库丢失数据的场景与原因,WAL、fsync、缓冲池等机制与数据安全。
2
为什么 MongoDB 使用 B 树
技术科普 深入解析 MongoDB 选择 B 树而非 B+ 树的设计原因,理解文档数据库的访问模式。
3
为什么数据库不应该使用外键
技术科普 深入解析为什么现代互联网应用中不建议使用外键,以及如何替代外键实现数据一致性。
4
为什么 MySQL 使用 B+ 树
技术科普 深入解析 MySQL 为什么选择 B+ 树作为索引结构,对比 B 树、哈希表等其他数据结构,理解数据库索引设计。
5
为什么 PostgreSQL 使用 MVCC
技术科普 深入解析多版本并发控制的设计原理,理解 PostgreSQL 如何实现高并发事务处理。






