如果你的数据仓库中的事实数据表拥有大量的数据(参见前文),存储和查询数据的难度会大大上升。
在大多数OLTP系统中,数据存储都是以面向行(row-oriented)的方式组织的。这种方式把一行数据存放在一起。
在OLAP系统中,查询语句一般是获取大量行数据中的特定某几列。这里就需要引入面向列(column-oriented)存储的概念:相比于面向行存储把一行数据相邻存放,面向列存储把一列的数据存放在一起。
面向列存储还有一个好处:处于同一列的数据往往具有某些相似性,这种特性会方便数据的压缩处理。
需要注意的一点是,谷歌知名的BigTable有一个列族(column families)的概念(HBase和Cassandra也一并继承了这个概念)。但是同一列族的数据仍然也行为单位存放在一起,所以BigTable本身更贴近于面向行的数据存储。
虽然面向列的存储把同一列的数据存放在一起,但是在常规查询的时候,还是应该按某一列的值按行把所有列的数据排序。比如某一操作需要经常按时间维度获取数据,正确的做法是按时间列升序或者降序来按行把所有数据排序,这样执行时间的区间查询时效率比较高。
如果排序列中只含有少数几个值的话,不妨使用bitmap将列进行压缩,来减少空间占用。
既然数据本身就要做冗余灾备,而且各个查询请求对排序列的要求也可能不同,不妨在不同的数据节点上按不同的排序列来存储多份数据。针对不同的查询请求,选择最合适的数据节点响应查询请求,发生了部分宕机之后最多造成查询条件下降。
前面说到,数据仓库常用做数据分析,这就意味着使用max
,min
,count
,sum
,avg
等方法比获取原始数据更为普遍。所以数据仓库常常对某些列的统计值进行缓存来减少计算量,这种方法叫物化视图(materialized view)。每当发生写操作时,物化视图都要被更新计算,所幸OLAP系统一般是周期性大批量写入,经常大批量读取。