本节介绍数据库的另一种分类:事务处理型(OLTP)和分析处理型数据库(OLAP)。

OLTP 和 OLAP 的定义就不在此重复了。主要的区别可以参见下面这个表:

属性 OLTP OLAP
主要的读模式 每个查询量都比较小,并且使用一个键来获取 在大量数据上进行聚合操作
主要的写模式 用户输入,随机写入,低延迟 批量插入,或者是事件流机制
主要被谁使用 终端用户,使用网络应用 分析师
有什么数据 最新的数据 历史发生的所有数据
数据集大小 GB 到 TB TB 到 PB

数据仓库

OLTP 数据库通常不允许分析师查询大量的数据做分析,因为扫描大量数据时间太长从而影响线上的并发查询性能。

因此,数据仓库的概念就由此而生了。数据仓库包含了一组来自很多 OLTP 数据库的可读数据的备份。

把数据从 OLTP 数据库移到数据仓库的过程叫做 Extract-Transform-Load (ETL),这个过程如下图所示:

ETL images here

之前讨论的索引方法在 OLTP 数据库上效果很好,然而它们对 OLAP 数据库的效果没那么好。

OLTP 数据库和 OLAP 数据库之间的差异

数据仓库通常都是关系型的。这是因为 SQL 语言是很通用而且很有表达力的语言。

价格!

星形模型和雪花模型

在之前的文章中看到过,OLTP 数据库有很多中数据模型,但是在 OLAP 数据库中,可选的模型就没那么多了。大多数都使用了 星形模型,也被称为维度模型

以下图为例:

data-warehouse-example.png

在这个模型中,处于中心位置的被称为事实表(fact-table),在本例中是 fact_sales,在事实表中的每一行都代表在一个特定时间发生了某个特定的时间,在本例中是某个用户购买了某个商品,当分析网站流量是,可以换成用户浏览和点击了某个页面。

事实表通常来说都很大。

在事实表中,有些是事件的属性,比如本例中的几个 price 字段。而另一些列的值相当于其他表的外键,这些表称为维度表

由于事实表可以被看做是事件的展现,因此维度表可以被看做是事件发生的who, whatwhere, when, how

星形模型名称的来源是:把事实表放在中间,维度表放在事实表的周围,它们之间的关系用线条来表示时,看起来就像是一颗星星一样。

另一种常见的模式叫做雪花模型,在雪花模型中,维度表进一步被拆解成更多的子维度表。

比如在本例中,dim_product 表中的 brandcategory 字段可以用 brand 表和 category 表的主键来表示。

雪花模型星形模型更加归一化,但是大家更喜欢用星形模型来实现数据仓库,因为更加简单。

在数据仓库中,表通常都是大宽表。不仅仅是事实表,维度表同样如此。

面向列的存储

在数据仓库中,事实表的存储通常是大家最为关心的,因为其数据量非常大。

虽然事实表通常都是大宽表,但是在分析查询的过程中通常只需要 4 到 5 个字段。

大多数 OLTP 数据库都是面向行存储,意味着每一行的所有数据都紧接着上一行所有数据存储,文档型数据库也一样。所以,如果事实表使用面向行存储的数据库,每行将有大量无用的数据被加载到内存。

面向列存储的原理是:将每一列的所有数据都连续得存储在一起。如果每一列的数据都单独存储在一个文件中,一次查询只用读这些想要的列文件就可以了。

列压缩

每列中有重复数据的概率非常大,因此对压缩很有利。
常用的压缩策略是:bitmap encoding(位图编码)(可以参见这篇文章)。见下图所示:

bitmap.png

查询对应的条件时,可以对位图进行相应的 AND(位与) 或者 OR(位或) 操作。

并行向量处理

列存储中的排序

理论上来说,对列存储引擎而言,行数据根本不用排序。
然而我们仍然可以像 SSTables 一样对其进行排序操作,从而起到索引的作用。

例如,如果时间是经常被范围查询的条件,那么可以将其作为第一个排序字段,从而减小范围查询的时间,不用全列扫描了。在第一个排序字段的基础上还可以继续添加后续的排序字段。

排序后还有一个好处是:可以帮助列压缩。如果首个排序字段的唯一值不多,将为压缩带来很大的好处。

向列存储写数据

所有这些优化都是为了大量读而设计的,但所有这些优化都为写数据带来困扰。

不能考虑就地更新类型的方式,比如 B-树,因为每一次写入都会更新所有的列数据,实在太糟糕了。

LSM-Tree 类型的存储方式就非常适合这种列存储数据库。

聚合:数据立方和物化视图

既然大部分数据仓库处理的数据都和聚合函数计算相关,那么为什么要浪费大量的运算资源来实时计算呢?另一种思路是:将常用的聚合函数和方法应用在数据上并缓存起来供以后使用。

一种产生这些缓存数据的方法是 物化视图

物化视图是将计算后的结果存在一张类似表的结构中,而这个表的数据是被写入硬盘中的。

由于每次数据更新都要更新这个物化视图,所以常见的 OLTP 数据库很少采用这个方式,但对于多读少写的 OLAP 数据库,这很合适。

一种常见的物化视图是数据立方。这是一个根据不同维度聚合而成的网表。

下图是一个二维数据立方:

two-demension-cube.png

基本思路如上图所示。

数据立方的优势在于对一些特定的聚合查询,速度非常快,因为已经提前计算好了。
劣势在于:不够灵活。

所以大部分数据库都尽量保存所有的原始数据,但对一些常见的聚合数据使用 数据立方 来提速。

第三章就此结束了。