行式存储(Row-based Storage)和列式存储(Column-base Storage)简介

〇、前言

简单来说,行式存储(Row-based Storage)就是将同一行的所有字段连续存放 ;列式存储(Column-base Storage)则将同一列的数据集中存放

它们代表了数据在磁盘或内存中组织的两种相反维度,现代数据库(如 ClickHouse、Hana、PostgreSQL 的部分插件)常根据业务需求选择其一,甚至支持混合存储引擎。

在日常开发中,它们非常重要。虽然普通业务代码可能不直接操作底层存储格式,但理解这一概念可以更清晰的判断如何选型数据库、设计表结构以及优化查询性能。如果选错存储模式可能导致分析查询慢几个数量级,或事务处理吞吐量大幅下降。

那么本文将就这两种存储方式分别进行简单的介绍和对比,先了解其基本信息,后续再进行简单实践,供参考。

一、什么是行式存储(Row-based Storage)?

行式存储是传统关系型数据库采用的存储方式,也是最常见的。

**数据以行为基本逻辑存储单位,同一行内的所有列数据在存储介质上连续存放。**如下示例:

复制代码
// 如下三行人员信息数据
行1: [张三, 25, 北京, 工程师, 3000]
行2: [李四, 30, 上海, 产品经理, 3500]
行3: [王五, 28, 广州, 设计师, 3200]
// 磁盘存储可以理解为连续的存储空间:
张三|25|北京|工程师|3000|李四|30|上海|产品经理|3500|....

这样行式存储的特点:按记录/行连续存储,每行包含所有字段;数据整行读取,效率高;支持高效的单行数据操作,如插入、更新、删除等;天然支持 ACID 事务特性;压缩效率较低,因为每一列的字段类型大概率是不同的

行式存储还可以通过索引来优化查询效率,例如 B+ 树等索引技术成熟,支持复杂查询优化。

但是,行式存储也有许多缺陷。首先是聚合查询慢 ,例如统计某列时需加载整行数据,造成 I/O 开销大;压缩率低 ,不同列数据类型混杂,难以高效压缩;扫描效率低,全表扫描时即使只需要少数列但也必须读取所有列。

**典型应用场景:**OLTP系统(在线事务处理)、银行交易系统、电商订单系统、企业ERP系统、在线支付系统等等。

代表数据库常见的有 MySQL、PostgreSQL、Oracle、SQL Server、DB2 等,都属于传统关系型数据库。

二、什么是列式存储(Column-Based Storage)?

列式存储是分析型数据库采用的存储方式。数据以列为基本逻辑存储单位,同一列的所有数据在存储介质上连续存放。

复制代码
// 还以三个人员信息举例,如下
姓名列: [张三, 李四, 王五, ...]
年龄列: [25, 30, 28, ...]
城市列: [北京, 上海, 广州, ...]
职位列: [工程师, 产品经理, 设计师, ...]
薪资列: [3000, 3500, 3200, ...]
// 磁盘上存储为:
张三|李四|王五|...|25|30|28|...|北京|上海|广州|...

这样的列式存储的特点:按列连续存储,每列独立成块;读取单列或部分列效率极高;适合批量写入,单行写入效率较低;压缩效率极高(同列数据类型相同);可通过向量化执行、SIMD指令等优化查询

由于是按照列存储,每个数据值类型都是一样的,因此相当于天然索引,查询效率直线飙升相同类型数据集中存储,CPU缓存命中率更高。

缺点:单行查询慢 ,读取完整记录需要跨多个列文件组装;写入操作复杂 ,单行插入/更新需要修改多个列文件,写放大明显;事务支持弱:ACID 事务实现复杂,通常不支持或支持有限。

典型应用场景:OLAP 系统(在线分析处理)、数据仓库、商业智能(BI)分析、大数据统计分析、时序数据处理。

代表数据库常见的有 ClickHouse、Vertica、Greenplum、Apache Kudu、MonetDB、Apache Parquet、Apache Druid 等。

三、行式和列式存储的区别和联系

3.1 两种存储方式的区别

  • 核心差异
对比维度 行式存储 列式存储
存储单位 行(Row) 列(Column)
数据布局 同一行数据连续存储 同一列数据连续存储
读取整行 ⭐⭐⭐⭐⭐ 极快 ⭐⭐ 较慢
读取单列 ⭐⭐ 较慢 ⭐⭐⭐⭐⭐ 极快
聚合查询 ⭐⭐ 效率低 ⭐⭐⭐⭐⭐ 效率高(10-100倍)
点查询 ⭐⭐⭐⭐⭐ 高效 ⭐⭐ 较低效
批量写入 ⭐⭐⭐ 中等 ⭐⭐⭐⭐⭐ 高效
单行写入 ⭐⭐⭐⭐⭐ 高效 ⭐⭐ 较低效
数据压缩 ⭐⭐ 压缩率低 ⭐⭐⭐⭐⭐ 压缩率高(5-10倍)
事务支持 ⭐⭐⭐⭐⭐ 完整 ACID ⭐⭐ 有限或无
I/O 效率 读整行少 I/O,读列多 I/O 读列少 I/O,读整行多 I/O
适用场景 OLTP(联机事务处理) OLAP(联机分析处理)
  • I/O 效率对比

|--------|--------------------------------------|---------------------------------|
| 操作 | 行式存储 | 列式存储 |
| 查询单行 | 只需一次 I/O 定位到该行 | 只需读取该列数据块,I/O 最小化 |
| 查询单列 | 需要读取所有行的完整数据,I/O 浪费严重 | 需要读取所有列文件并组装,I/O 开销大 |
| 示例 | 1 亿行数据,每行 100 列,查询 1 列需读取 100 倍不必要数据 | 同样 1 亿行数据,查询 1 列只需读取 1/100 的数据量 |

  • 压缩效率对比
压缩因素 行式存储 列式存储
数据类型一致性 低(混合类型) 高(单一类型)
重复值集中度
典型压缩比 2-3倍 5-10倍
压缩算法适配 通用压缩 字典编码、游程编码等

为什么列式存储的压缩效率比较高?

  • 同一列数据类型相同,便于采用针对性压缩算法;
  • 同一列数据值分布相似,重复值集中
  • 可使用字典编码、游程编码(RLE)、位图编码等高效压缩。
  • 性能对比实验数据

据资料可得到大概的结果:

查询类型 行式存储耗时 列式存储耗时 性能提升
SUM(单列) 1000ms 50ms 20 倍
AVG(单列) 950ms 45ms 21 倍
COUNT 800ms 40ms 20 倍
单行点查 5ms 50ms 行存快 10 倍
批量插入 1000 行/s 10000 行/s 列存快 10 倍

3.2 行式存储和列式存储的联系

首先是互补关系,而非替代关系。

  • 现代架构中的"互补"实践:HTAP 与 混合负载

正因为两者不可互相替代,现代数据库架构倾向于将它们结合使用,形成互补:

行列混合存储引擎(Hybrid Storage):

如 SAP HANA,Oracle In-Memory,ClickHouse(部分特性),TiDB。

这些系统在同一份数据上维护行式和列式两种视图,或者允许用户指定某些表/列使用行存,某些使用列存。

热数据 (频繁读写)走行存路径保证事务速度;冷数据或分析请求自动路由到列存路径进行加速。

链路分离(ETL/ELT):

前端:业务系统使用行存数据库(如 MySQL,PostgreSQL)处理交易

后端:通过同步工具将数据实时/准实时地复制到列存数据仓库(如 Snowflake, Doris, StarRocks)进行分析

这是最经典的互补模式:行存负责"生产数据",列存负责"消费数据"

四、小小的总结

行式存储和列式存储的关系就像螺丝刀和锤子:不能用锤子去拧螺丝(列存做不了高频事务);也不能用螺丝刀去钉钉子(行存做不了高效分析)。

它们在数据处理的生命周期中扮演不同的角色:行存保障了业务的实时性和事务一致性,列存保障了决策分析的效率和成本。因此,它们是构建完整数据生态系统中不可或缺的互补组件。

相关推荐
l1t9 小时前
DeepSeek总结的 pg_regresql插件:真正可移植的 PostgreSQL 统计信息
数据库·postgresql
oradh10 小时前
Oracle 11.2.0.1版本升级至11.2.0.4_单机环境
数据库·oracle·oracle11g·oracle升级
l1t10 小时前
用docker安装测试crate数据库
数据库·docker·容器·cratedb
anzhxu10 小时前
QT数据库(三):QSqlQuery使用
数据库·qt·oracle
身如柳絮随风扬10 小时前
MySQL核心知识
数据库·mysql
德彪稳坐倒骑驴10 小时前
Oracle 11g安装
数据库·oracle
韩立学长10 小时前
Springboot校园跑腿业务系统0b7amk02(程序、源码、数据库、调试部署方案及开发环境)系统界面展示及获取方式置于文档末尾,可供参考。
数据库·spring boot·后端
阿贵---10 小时前
使用XGBoost赢得Kaggle比赛
jvm·数据库·python
想七想八不如1140810 小时前
数据库--样题复习
数据库·sql·oracle