站在行式存储的肩膀上实现列式存储

参考《Column-Stores vs. Row-Stores: How Different Are They Really?》

从行式存储系统中利用底层列式存储,其实是在探究一个问题,那就是列式存储格式的增益大(磁盘I/O占主导因素),还是在其之上构建的写入和查询引擎带来的增益大。

接下来介绍几种设计方案,以下都针对一个表来说。

列式分区

这其实就是 DSM 。将原始表中的每个列都单独存一张表,并配上一个递增的0、1、2、3的列 index 用来将不同列对齐。

比如原来表有 a,b,c 三列,现在建立三个表,分别为(index,a),(index,b),(index,c)。

在纯种的列存系统中,可以通过各个列中数据的下标来拼接数据,但是传统数据库里可没这个东西,表之间的拼接是通过 join 实现的,所以必须加上一列以便拼接数据。 但是,这样做有个缺点,每一列其实都是两行数据,不能称为严格意义上的列式存储,只能尽量使每一行的数据量最少。

多物化视图

搞一堆物化视图,物化视图可以看成一个物理表,表结构可以定义,数据可以自己填充,一般是将一个查询的结果存成一个表。在这里的处理方法是:针对每个查询,都有一个刚好包含其需要的列的物化视图相对应。

这种方式其实是第一种完全列式和完全行式的折中版。针对每个查询,去掉了那些没用的列,在剩下的表中进行行式查询。可以预见,这种方式比单个表查询要快。但是,这种方式极其占用空间,仅仅是一个实验品。

各列索引

表还是一个表,但是在行式存储模型上构建了一层虚拟的列式存储索引。

具体方法是:为表中的主键和每一列分别建立索引,如B+tree。当接收到针对某一列的过滤条件时,先在各列索引上过滤找出对应的主键,最后合并主键。这里的主键就充当了 index 的功能,用来对齐数据。

这种方式其实是在物理上的行式存储基础上实现了逻辑上的列式存储。

对比

除第二种方式比传统的关系数据库性能好(那是肯定的,每个物化视图都对一种查询进行了优化,剪掉了不需要的列),第一种和第三种都比传统关系数据库差。在一种商用关系型数据库上的测试结果如下图:

其中T是传统关系数据库,T(B)是应用bitmap位图索引辅助查询计划生成(可以忽略这列),MV是多个物化视图的,VP是列式分区,AI是各列索引。因为各个列上操作索引,单个对象的负担比较重,所以VP和AI都比传统的关系数据库还慢。

总结

人出生是不带任何属性与偏好的,但是系统不是,从系统面向场景确定的那一刻,系统就具有了强烈的针对这些场景的优势。在原来的系统上搭建引擎相对省时省力,但是很多时候,天生的就是比后天的要好。

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20180705G11WTX00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券