知识卡片

行式存储与列式存储的优劣,本质取决于访问模式而非绝对优劣

结构图卡

内容

[[NoSQL的本质定位是针对关系数据库四大缺陷的补充方案]]里列式数据库(以HBase为代表)针对的是”大数据场景I/O高”这个缺陷,与之相对的关系数据库是按行存储数据(行式存储)。行式存储的优势体现在两方面:一次业务操作要同时读取一行里的多个列时效率很高(同一行的各列本就物理相邻,一次磁盘操作就能全部读入内存);能一次性完成对一行内多个列的写操作,天然保证了行级写操作的原子性和一致性——如果换成列式存储,理论上可能出现同一次写操作里某些列成功、某些列失败,导致行内数据不一致。但这些优势只在特定访问模式下成立,一旦场景变了(典型是海量数据统计),行式存储的优势会直接反转成劣势:比如统计某城市所有居民的体重超标情况,逻辑上只需要读取”体重”这一列,但行式存储即使最终只用一列,也必须把整行数据(假设每行1KB,体重字段只占4字节)全部读入内存,造成明显浪费;换成列式存储,每个用户只需读取体重那4字节,I/O会大幅减少。列式存储除了省I/O,还有更高的压缩比——行式数据库压缩率一般在3:1到5:1,列式数据库能达到8:1到30:1,因为同一列内的数据相似度天然比同一行内跨字段的数据相似度高,压缩效果自然更好。但列式存储同样有对应场景下的劣势:如果业务需要频繁更新多个列,由于不同列在磁盘上物理不连续,更新会变成随机写,效率远低于行式存储”一次磁盘写完成整行更新”的效率;而且列式存储的高压缩率在更新场景下也变成负担,因为更新前要先解压、更新后要再压缩才能写回磁盘。基于这组此消彼长的取舍,列式存储通常只用在离线的大数据分析和统计场景——这类场景的特点正好是主要针对少数列做单列运算、且数据写入后基本不再更新删除,恰好避开了列式存储的短板、发挥它的长处。

结构图

flowchart LR
  A["行式存储(关系数据库)"]
  A --> A1["优势:同时读多列快<br/>行内多列写操作原子性有保证"]
  A --> A2["劣势场景:海量数据单列统计<br/>只用一列也要读整行→I/O浪费"]
  B["列式存储(HBase)"]
  B --> B1["优势:单列统计I/O小<br/>压缩比更高(8:1~30:1 vs 行式3:1~5:1)"]
  B --> B2["劣势场景:频繁多列更新<br/>列物理不连续→随机写效率低<br/>+ 压缩带来的解压/重压开销"]
  A2 --> C["列式存储适用:离线大数据分析统计<br/>针对少数列运算,数据写入后基本不更新删除"]
  B2 --> C

参考来源

- 位置:《从零开始学架构》第16讲《高性能NoSQL》"列式数据库"(源文件:_epub-src/OEBPS/text00001.html) - 结论依据:原文说明行式存储优势"业务同时读取多个列时效率高……能够一次性完成对一行中的多个列的写操作,保证了针对行数据写操作的原子性和一致性",并以体重统计为例说明列式存储节省I/O,"列式数据库的压缩率一般在 8:1 到 30:1 左右",同时指出"如果需要频繁地更新多个列……列式存储的随机写效率要远远低于行式存储的写效率",最终"一般将列式存储应用在离线的大数据分析和统计场景中",直接支撑本卡片结论与结构图。 - 原始内容:业务同时读取多个列时效率高……能够一次性完成对一行中的多个列的写操作,保证了针对行数据写操作的原子性和一致性……列式数据库的压缩率一般在 8:1 到 30:1 左右……一般将列式存储应用在离线的大数据分析和统计场景中。