列式存储机制

引言


由于大数据的发展,越来越多的企业利用大数据来挖掘数据更多的价值,关系型数据库受到了越来越严重的挑战。人们迫切需要找到一个新的突破口来处理大数据。在这样的环境下,列式存储孕育而出。

什么是列式存储


简单的说,列式存储就是将相同字段的数据放在一起存储。

传统的行式数据库将一个个完整的数据行存储在数据页中。如果处理查询时需要用到大部分的数据列,这种方式在磁盘IO上是比较高效的。一般来说,OLTP(Online Transaction Processing,联机事务处理)应用适合采用这种方式。

列式数据库是将同一个数据列的各个值存放在一起。插入某个数据行时,该行的各个数据列的值也会存放到不同的地方。

列式存储的优点


  • 高效的存储空间

由于列在概念上是相同的,所以对于同一列,他们的数据必然有着极大的关联性。在这样的情况下,就可以通过压缩列来减少存储空间。

感觉别人写的比较好,还是采用拿来主义吧:

  1. 传统的行式数据库由于每个列的长度不一,为了预防更新的时候不至于出现一行数据跳到另一个block 上去, 所以往往会预留一些空间。而面向列的数据库由于一开始就完全为分析而存在,不需要考虑少量的更新问题,所以数据完全是密集储存的。
  2. 行式数据库为了表明行的id 往往会有一个伪列rowid 的存在。列式数据库一般不会保存rowid。
  3. 列式数据库由于其针对不同列的数据特征而发明的不同算法使其往往有比行式数据库高的多的压缩率,普通的行式数据库一般压缩率在3:1 到5:1 左右,而列式数据库的压缩率一般在8:1到30:1 左右。(InfoBright 在特别应用可以达到40:1 , Vertica 在特别应用可以达到60:1 , 一般是这么高的压缩率都是网络流量相关的)
  4. 列式数据库由于其特殊的IO 模型所以其数据执行引擎一般不需要索引来完成大量的数据过滤任务(Sybase IQ 除外) 。这又额外的减少了数据储存的空间消耗。

  5. 列式数据库不需要物化视图,行式数据库为了减少IO 一般会有两种物化视图,常用列的不聚合物化视图和聚合的物化视图。列式数据库本身列是分散储存所以不需要第一种,而由于其他特性使其极为适合做普通聚合操作。(另外一种物化视图是不能实时刷新的,比如排名函数,不规则连接connect by 等等,这部分列数据库不包括。)

  • 不可见索引

列式数据库由于其数据的每一列都按照选择性进行排序,所以并不需 要行式数据库里面的索引来减少IO 和更快的查找值的分布情况。

  • 数据迭代

现在的多核CPU 提供的L2 缓存在短时间执行同一个函数很多次的时候能更好的利用CPU 的二级缓存和多核并发的特性。而行式数据库由于其数据混在一起没法对一个数组进行同一个简单函数的调用,所以其执行效率没有列式数据库高。

  • 压缩算法

    列式数据库由于其每一列都是分开储存的。所以很容易针对每一列的特征运用不同的压缩算法。常见的列式数据库压缩算法有Run Length Encoding , Data Dictionary , Delta Compression , BitMap Index , LZO , Null Compression 等等。根据不同的特征进行的压缩效率从10W:1 到10:1 不等。而且数据越大其压缩效率的提升越为明显。

  • 延迟物化

    列式数据库由于其特殊的执行引擎,在数据中间过程运算的时候一般不需要解压数据而是以指针代替运算,直到最后需要输出完整的数据时。

  • 列式数据库的适用场景

列式数据适合处理大量的数据,通常在列很多的时候更具优势。他不适合行的更新和删除操作。

一个OLAP类型的查询可能需要访问几百万甚至几十亿个数据行,且该查询往往只关心少数几个数据列。例如,查询今年销量最高的前20个商品,这个查询只关心三个数据列:时间(date)、商品(item)以及销售量(sales amount)。商品的其他数据列,例如商品URL、商品描述、商品所属店铺,等等,对这个查询都是没有意义的。

在这种情况下,它只会扫描少量的列,而行式存储需要扫描所有的列。所有,对于olap查询,列式存储更具有优势。

当然,列式数据库不是万能的,每次读取某个数据行时,需要分别从不同的地方读取各个数据列的值,然后合并在一起形成数据行。因此,如果每次查询涉及的数据量较小或者大部分查询都需要整行的数据,列式数据库并不适用。

总结


  优点:

* 极高的装载速度 (最高可以等于所有硬盘IO 的总和,基本是极限了)
* 适合大量的数据而不是小数据
* 实时加载数据仅限于增加(删除和更新需要解压缩Block 然后计算然后重新压缩储存)
* 高效的压缩率,不仅节省储存空间也节省计算内存和CPU。
* 非常适合做聚合操作。

  缺点:

* 不适合扫描小量数据
* 不适合随机的更新
* 批量更新情况各异,有的优化的比较好的列式数据库(比如Vertica)表现比较好,有些没有针对更新的数据库表现比较差。
* 不适合做含有删除和更新的实时操作。

常见误区


一个常见的误区认为如果每次扫描较多行或者全列全表扫描的时候,行式数据库比列式数据库更有优势。事实上这只是行式数据库认识上的一个误区,即认为列式数据库的主要优势在于其列分开储存,而忽略了列式数据库上面提到的其他几大特征,这个才是列式数据库高性能的核心。