mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
570 字
2 分钟
为什么 OLAP 需要列式存储
2023-11-10

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_count
FROM orders
WHERE region = '华东'
GROUP BY 1, 2
HAVING SUM(amount) > 100000
ORDER BY 1, 4 DESC
LIMIT 100;

2.2 查询特征#

特征OLAPOLTP
查询类型聚合、聚合、再聚合单条读写
扫描范围大量行,少量列少量行,全部列
并发低并发,大查询高并发,小查询
延迟允许秒级必须毫秒级

三、列式存储的优势#

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)
# 伪代码:计算 AVG
values = column_reader.read('salary', 1024) # 一次读 1024 个值
sum = simd_sum(values) # SIMD 指令并行求和
count = 1024
avg = 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 的事务型场景仍需要行式存储。

参考资料#

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

为什么 OLAP 需要列式存储
https://blog.souloss.com/posts/why-the-design/why-olap-needs-columnar-storage/
作者
Souloss
发布于
2023-11-10
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时