SQL数据库列存储原理_行存与列存对比

14次阅读

列存储将同一列数据连续存放,提升分析查询效率与压缩比,但写入性能较差;行存则整行存储,适合事务处理。

SQL数据库列存储原理_行存与列存对比

sql数据库里的列存储,核心是把同一列的所有值连续存放在磁盘或内存中,而不是像行存那样把整条记录(比如用户ID、姓名、年龄)捆在一起存。这种“按列组织数据”的方式,直接决定了它在分析类查询中效率高、压缩比大,但在事务写入时更吃力。

列存储是怎么组织数据的

假设一张表有三列:user_id(整型)、action(字符串)、ts(时间戳),共100万行数据:

  • 行存会把每行拼成一个单元,比如[1, “click”, “2025-01-01″] → [2, “view”, “2025-01-01”] → …,顺序写入磁盘块;
  • 列存则拆开存放:user_id列单独存为一串整数[1, 2, 3, …, 1000000]action列存为字符串数组[“click”, “view”, “buy”, …]ts列存为统一格式的时间序列——各列物理上完全分离。

这样做的直接好处是:查“所有action类型分布”,只需读action列那一段;做SUM、AVG、GROUP BY,引擎能顺序扫描同质数据,CPU缓存友好,还能用RLE、字典编码算法高效压缩。

行存和列存的关键差异在哪

差异不在“好不好”,而在“适合什么场景”:

  • 读取逻辑不同:行存一次加载整行,适合点查(如select * FROM users WHERE id = 123);列存只加载涉及的列,适合宽表扫描(如SELECT count(*), AVG(age) FROM logs WHERE dt = '2026-01-04');
  • 写入机制不同:行存插入一行=一次定位+一次写入;列存需分别写入N个列块,磁头寻道/页分裂开销更大,尤其单行更新代价高;
  • 压缩能力不同:列内数据类型一致、重复模式多(比如status列大量是”success”),压缩率常达5–10倍;行存混杂不同类型字段,压缩收益有限;
  • 索引与优化倾向不同:列存天然具备“每列即索引”的特性(比如对某列建位图索引非常轻量),优化器更倾向向量化执行、谓词下推;行存依赖B+树等传统索引结构,优化重心在连接、事务一致性。

哪些SQL数据库支持列存

不是所有SQL数据库都原生支持列存,但主流系统已有明确分工或混合能力:

  • 纯列存SQL引擎clickhouseapache Doris、StarRocks、Vertica——默认按列组织,专为OLAP设计;
  • 支持列存扩展的通用数据库postgresql(通过citus或columnar插件)、SQL Server(支持聚集列存储索引)、oracle(In-Memory Column Store选项)、PolarDB(mysql版提供行列混合模式);
  • 典型行存为主,不默认列存:MySQL(InnoDB引擎)、PostgreSQL(默认表)、sqlite——它们的底层存储面向事务,列存需额外组件或升级版本实现。

选型时不用纠结“哪个更好”,而要看你主要跑的是UPDATE user SET balance = balance - 100 WHERE id = 888,还是SELECT region, SUM(sales) FROM fact_sales GROUP BY region——前者行存稳,后者列存快。

text=ZqhQzanResources