为什么要选择列式存储
行式存储和列式存储主要是在物理存储的选择上面,这里主要是选择从实体的完整性角度进行存储,还是从实体特征维度进行存储,行式存储就是以实体为单位进行存储,在物理存储上,一个实体(的特征属性)紧挨着另外一个实体;列式存储就是从实体特征维度进行存储,通常是以列为物理存储单元,这种存储模式也决定了查询的模式也是基于列取查询;所以,当我们想要按照实体去查询列式存储的数据,一般都是需要并行查询,所以列式存储天生的是分布式数据库的架构。
在OLTP场景,更多的基于实体的维护和查询,但是在OLAP场景,则是更多地从实体特征角度进行数据处理(统计),所以在OLAP的场景下,如果还是使用行式存储,会导致大量的无谓的遍历,比如想要对某个列进行所有数据的统计,因为是行式存储,需要遍历所有的实体的所有的属性;如果列式存储,则只需要按照列进行查询即可,因为列式存储是以列一个物理存储单元,所以遍历只要遍历相应列的物理存储文件即可。
那么从这个角度上面来讲,HBase其实是行列存储的一个综合体,从宏观角度是按照列簇为单位进行存储,从微观角度,每一个列簇的单元是由key,value的键值对组成(可能是很多歌键值对,因为一个列簇可以包含很多列),但是values其实是行式存储,另外HBase并不建议采用度过列簇,列簇不要超过2个,所以列式存储的优势并没有完全发挥出来,但是基于HBase的技术架构,只能这样处理,如果是纯粹的列式存储对于HBase的性能会有大影响。
采用列式存储还有一个好处就是可以方便的进行编码和压缩,因为一列中的值大概率是有大量重复的,可以对于这些重复的值进行编码以及压缩,节省存储空间。
为什么HBase建议列簇不要超过2个
1. memstore只要一个满了就会刷,未满的列簇会形成大量的小文件,增加查询成本;以及会潜在增加compact的次数(文件数量、文件大小都会导致compact);
2. 文件的Split也有类似问题,只要一个列簇文件大小达到了split,就会将这个region下所有的列簇的进行分割。
综合来看,上述两点其实描述了HBase处理数据的特点,就是只要一个列簇满足条件,那么这个region下面所有的列簇都会因此而被触发相应操作,就是我们通常讲的“躺枪”。注意,这里强调HBase的相关操作都是在Region级别完成的,分布式嘛,各自维护好自己那一块。