关系型与非关系型数据 行与列存储 解析

这个是数据库选型的核心。为了清晰理解,我们分两层拆解:第一层是数据模型(关系型 vs 非关系型)第二层是存储引擎(行存储 vs 列存储)。这两层是正交的,可以交叉组合。


第一层:数据模型(关系型 vs 非关系型)

这决定的是数据如何组织用什么语言操作

  • 关系型数据库(SQL)

    • 核心 :数据存成二维表格 ,表与表之间通过外键 关联。必须有固定的Schema(表结构),像Excel模板,每行每列固定。

    • 操作语言SQL(结构化查询语言),支持复杂的多表联合查询(JOIN)和事务(ACID)。

    • 典型产品:MySQL、PostgreSQL、Oracle。

    • 适用场景强一致性要求的场景,如银行转账、订单系统、ERP(企业资源计划系统)。数据完整性比性能更重要。

  • 非关系型数据库(NoSQL)

    • 核心Schema-less(无固定模式),存储结构灵活。细分为四大家族:

      • 键值型(Redis):像超大字典,通过Key找Value,极快。

      • 文档型(MongoDB):存JSON文档,嵌套结构,适合灵活迭代的业务。

      • 列族型(HBase/Cassandra):注意!这里的"列族"是数据模型,不是底层的列存储,后面会区分。

      • 图型(Neo4j):存节点和关系,专攻社交网络、知识图谱。

    • 操作语言:各家用各自的API或类SQL语法,通常不支持多表JOIN。

    • 适用场景高并发、海量数据、快速迭代,如缓存、日志、物联网实时数据。


第二层:存储格式(行存储 vs 列存储)

这决定的是数据在磁盘上如何物理排列 。这是数据库性能差异的关键,尤其影响查询速度。

用一个例子对比,假设有张用户表:

ID(主键) 姓名 年龄 城市
1 张三 28 北京
2 李四 32 上海
3 王五 24 深圳
  • 行存储(Row-Oriented)

    • 物理排列 :磁盘上按 连续存放。像这样:1,张三,28,北京 | 2,李四,32,上海 | 3,王五,24,深圳

    • 特点写操作极快 (一次IO写一整行),查询整行极快SELECT *)。

    • 痛点 :如果只查年龄总和SELECT SUM(年龄)),数据库仍需把整行数据(含姓名、城市)全部读入内存,再过滤出年龄,IO浪费严重

    • 典型产品:MySQL InnoDB、PostgreSQL。

  • 列存储(Column-Oriented)

    • 物理排列 :磁盘上按 连续存放。像这样:1,2,3 | 张三,李四,王五 | 28,32,24 | 北京,上海,深圳(每列单独存储)。

    • 特点查询特定列极快 (只读取需要的列数据块),压缩率极高(同一列数据类型相同,比如年龄列全是数字,压缩比可达10:1)。

    • 痛点写入慢 (插入一行要分散写入多个列文件),查整行慢(需要从多个列文件拼凑数据)。

    • 典型产品:ClickHouse、Apache Parquet(大数据文件格式)、HBase底层(LSM树,但这里先不展开)。


第三层:实战组合(打破认知)

很多人误以为"关系型=行存,非关系型=列存",这是错误 的。真实世界是混合体

组合方式 典型产品 适用场景
关系型 + 行存 MySQL、PostgreSQL OLTP(在线交易) 。银行扣款、下单支付。需要频繁增删改,且每次查一行或少量行。
关系型 + 列存 Greenplum、ClickHouse(兼容SQL) OLAP(在线分析) 。BI报表、销售大盘。数据只追加不修改,海量数据按年汇总,只查几列。
非关系型 + 行存 MongoDB、Redis 业务缓存文档存储。通常按ID取整个JSON对象,极少做全表统计。
非关系型 + 列存 HBase、Cassandra(宽表) 海量Key-Value查询。比如查某个用户的手机号、地址,按主键取回整行数据的所有列,但底层按列族存储以节省空间。

终极选择指南(决策树)

当你做技术选型时,可以按这个逻辑问自己:

  1. 数据需要强一致性和多表关联吗?

    • → 选关系型(MySQL/PostgreSQL)。

    • → 选非关系型(MongoDB/Redis)。

  2. (在关系型内部)你的查询主要是单条点查,还是全表聚合?

    • 点查/频繁更新 (如订单ID查详情)→ 行存储(MySQL)。

    • 海量数据统计 (如计算过去10年总销售额)→ 列存储(ClickHouse)。

  3. (在非关系型内部)你的数据是复杂对象,还是单纯的大Key?

    • 复杂嵌套 (如商品评论、用户画像)→ 文档型(MongoDB),默认行存。

    • 单纯的海量KV (如用户状态)→ 列族型(HBase),底层优化列存。


最后,一个极简口诀

行存管交易(OLTP),列存做分析(OLAP);关系型管关联,非关系型管海量。