行式存储和列式存储
1.从一个例子说起
- 要理解行式存储和列式存储以及他们之间的差异首先就得理解两种存储方式在结构上的差异,举个例子,如下表所示为一张学生的学科表:
id | subject | date |
---|
1 | 计算机概论 | 大一 |
2 | 数据结构 | 大二 |
3 | 计算机网络 | 大三 |
- 在了解了他们的结构后二者的差异就能很清楚的理解了。
2.二者的差异
2.1 写操作
- 从他们的结构上可以看出,行存储在写入时比列存储要快(eg:如果是机械硬盘,列存储时磁头在磁盘上只需要顺序写入,而列存储需要频繁的移动定位到下一个字段需要写入的地址,造成了时间上的开销);同时由于行存储下表的数据是放在一起的,一次写入,所以数据的完整性可以确定;
2.2 读操作
- 读操作涉及情况种类比较多,不同情况对两种存储方式来说效率也不同,我们不妨先假设以下几种情况;
- 我们需要查询表中所有大一所开设的课程的所有id,如果是行存储,那么在查询时势必会将课程名和年级一起查询出来,这么一开就造成了数据的冗余,而冗余的数据列使我们不需要的,这个例子中只有三个字段,此影响比较小,如果是20个字段呢,就会有19个冗余的字段,此时就会影响到处理数据的效率了;那如果是列存储呢?这就方便很多了,因为列存储是按列存储在一起的,所以每列都单独存放,每一行数据即为整个表的索引,所以在将大三这个值和date列上的所有值比对后就能很快通过索引查询到课程名了;
- 假设我们需要查询所有书籍的所有信息,通过上面已经知道列存储每一列单独存放,此时我们需要先查询出每一列,然后再通过聚集运算(如果数据有压缩还必须进行解压缩,压缩这一点我会在下文中讲到)把列上的每个数据拼接成行,同理,在只有三个字段下的情况下开销会比较小,但是增加到20乃至更多的列数时带来的开销就比较大了,而行式存储在这种情况下就显得更加合适。
2.3 数据存储
2.3.1 压缩
- 还是用这个学科表的例子,如果我们只用二进制数字来表示学科开设的年级(date),比如说:00表大一、01表大二、10表大三、11表大四,那么我们这个表可以变成下两张表:
id | subject | date |
---|
1 | 计算机概论 | 00 |
2 | 数据结构 | 01 |
3 | 计算机网络 | 10 |
date_before | date_after |
---|
大一 | 00 |
大二 | 01 |
大三 | 10 |
大四 | 11 |
我们假设date原来是char(4)类型,也就是4个字节,压缩后,我们可以用一个字节存储,当数据的记录条数非常大时,可节约的空间是非常大的;
- 同样让我们看看行存储和列存储在这种情况下的压缩情况,可以很清楚的看到,由于列存储的结构(按列存储,数据类型一致),压缩对他而言是轻而易举的,只需要读取该列上的数据然后顺序替代成压缩后的数据即可,这个过程是非常快的;
2.3.2 存储效率
- 很多传统的行式存储数据库为了加快查询效率,通常会建立索引,而建立所有需要耗费数据库的空间资源,也会增加时间开销,而列式存储因为数据即索引,所以空间开销会好很多,只访问查询所涉及的列时,可以大大降低系统IO开销
3. 使用场景总结
行存储 | 列存储 |
---|
需要频繁的更新和插入数据时 | 数据更新和增加比较慢时 |
需要经常查询整行数据尤其是查询所有的数据时 | 经常只需要经常查询少数几列的数据的时 |
数据表的数据字段比较多时 | 数据表的字段比较少时 |
没有快速查询的需求时 | 有快速查询的需求时 |
数据表中字段的重复数据少,唯一性强 | 数据表中重复数据多,适合压缩 |
数据的记录(行)比较少时 | 数据的记录比较多时 |
对数据库的存储容量要求不严格时 | 对数据库的存储空间十分严格时 |
谢谢您的阅读,如有错误请随时指教