列式存储
重点介绍下列式存储,它与关系型数据库的行式存储有什么区别。
现有一张数据表:
数据读取:
在关系型数据库中,是以实体(记录、行)结构存储,数据在存储的时候在磁盘上是一行的数据是相邻的,如mysql的数据,它的一行数据都是在一起的,那么它在磁盘上存储就是如下图所示:
ps:每一行之间可能不是数据存储可能不是相邻,但是它每一行里面的数据是相邻的
而在列式存储结构中,它是每一列的数据是尽量相邻的,如下图所示:
在数据批量处理和选择的时候,列式存储性能要高于行式存储的,如我们现在要完成这样一条sql需求:
select name from student
。在行式存储中我们需要从头扫描到尾,也就是我们所说的全表扫描,才能收集完成整个数据。
使用列式存储的时候,只需要定位到
name
列的开始位置,就可以扫描顺序扫描到结尾即可完成结果收集。
可以看到,只需要扫描三个单元格就完成了结果的收集,而行扫描需要扫描九个单元格。
另外即使是在
select col1,col2,col3 from xxx
的情况下,列读取依旧比行快,因为它只需要知道列的开始就可快速扫描到结尾,而不必做一些无效的扫描。
因此列式存储在列选择模式下读取性能高于行存储。列批处理的情况下由于列数据紧凑的特性,对列数据批处理基于其读优秀的特性也比较好。(优点)
但是在随机行访问的情况下就性能较差了,比如我现在就要获取张三的所有信息,此时它们两个的角色就互换了,列式存储会扫描很多无效数据,而行扫描就快很多了,只需要扫描数据长度即可。(缺点)
数据压缩:
数据压缩:
列式存储在数据压缩层面来说,它的压缩率较高,如现在我们对这个表新增一列
car
有车的同学就填上车的型号,没有的就不填
那么整个班级,就张三同学有车,但是其它都没有。
在关系型数据库行式存储就会空出来多余的空间被浪费,虽然现在有varchar这种优化手段,但是还是有一定消耗。
在列式存储中,就可以由于列数据紧密型存储,就可以进行空间压缩省去没有数据的空间:
从上面可以看到,在数据压缩和空间利用率这一块,列式存储肯定是优于行式存储的(优点) 但是也因此带来了一个其它很严重问题就是数据写入。
数据写入:
由于行式存储是预留空间,加上行记录紧密型,如现在要插入一条记录
insert into students values('04','赵六','21',null);
,那么在行式存储中,只需要进行追加就行了,而在列存储中会影响已经存储的数据,造成多次IO。
就像别人已经排好队了,你突然去插队,那肯定会导致后面的人往后挪,造成多次磁盘IO。
总结一下:
区别:
- 存储方式:行式存储将一整行数据连续地存储在一起,而列式存储将同一列的数据连续地存储在一起。
- 读取方式:行式存储需要读取整行数据,即使只需要其中的一部分列数据。而列式存储只需要读取所需列,而不需要读取整行数据,从而减少了不必要的读取量。
- 压缩效率:列式存储在压缩方面更加高效,因为相同类型的数据在列中连续存储,相似的数据值更容易被压缩。
- 查询性能:对于特定列的查询和聚合操作,列式存储具有更高的性能,因为只需要读取相关列的数据,而行式存储需要读取整行的数据。
优缺点:
列式存储的优点:
- 高压缩率:由于相似的数据值在列中连续存储,列式存储可以更高效地进行数据压缩,减少存储空间的占用。
- 高效的查询性能:对于特定列的查询和聚合操作,列式存储具有更高的查询性能,能够快速过滤和检索所需的数据。
- 灵活的数据模型:列式存储支持动态添加和删除列,可以根据业务需求灵活调整数据模型。
列式存储的缺点:
- 写入性能较低:由于数据按列存储,写入时需要将数据写入到对应列的位置,可能需要更多的磁盘I/O操作,导致写入性能相对较低。
- 不适用于随机访问:如果需要随机访问整行数据或需要频繁更新整行数据,列式存储可能不是最优选择。
行式存储的优点:
- 写入性能较好:由于数据按行存储,写入整行数据时只需要在连续的位置写入数据,相对较快。
- 适用于随机访问:对于需要频繁进行随机访问整行数据的场景,行式存储更加适用。
行式存储的缺点:
- 查询性能相对较低:对于特定列的查询和聚合操作,需要读取整行的数据,可能读取了大量不必要的数据,降低了查询性能。
- 压缩率较低:由于相同类型的数据在行中存储,相似的数据值可能被打散存储,导致压缩率较低。