野猪书读书笔记第三章(续二)

本节介绍数据库的另一种分类:事务处理型(OLTP)和分析处理型数据库(OLAP)。
OLTP 和 OLAP 的定义就不在此重复了。主要的区别可以参见下面这个表:
属性 | OLTP | OLAP |
---|---|---|
主要的读模式 | 每个查询量都比较小,并且使用一个键来获取 | 在大量数据上进行聚合操作 |
主要的写模式 | 用户输入,随机写入,低延迟 | 批量插入,或者是事件流机制 |
主要被谁使用 | 终端用户,使用网络应用 | 分析师 |
有什么数据 | 最新的数据 | 历史发生的所有数据 |
数据集大小 | GB 到 TB | TB 到 PB |
数据仓库
OLTP 数据库通常不允许分析师查询大量的数据做分析,因为扫描大量数据时间太长从而影响线上的并发查询性能。
因此,数据仓库的概念就由此而生了。数据仓库包含了一组来自很多 OLTP 数据库的可读数据的备份。
把数据从 OLTP 数据库移到数据仓库的过程叫做 Extract-Transform-Load (ETL),这个过程如下图所示:

之前讨论的索引方法在 OLTP 数据库上效果很好,然而它们对 OLAP 数据库的效果没那么好。
OLTP 数据库和 OLAP 数据库之间的差异
数据仓库通常都是关系型的。这是因为 SQL 语言是很通用而且很有表达力的语言。
价格!
星形模型和雪花模型
在之前的文章中看到过,OLTP 数据库有很多中数据模型,但是在 OLAP 数据库中,可选的模型就没那么多了。大多数都使用了 星形模型,也被称为维度模型。
以下图为例:

在这个模型中,处于中心位置的被称为事实表(fact-table),在本例中是 fact_sales,在事实表中的每一行都代表在一个特定时间发生了某个特定的时间,在本例中是某个用户购买了某个商品,当分析网站流量是,可以换成用户浏览和点击了某个页面。
事实表通常来说都很大。
在事实表中,有些列是事件的属性,比如本例中的几个 price 字段。而另一些列的值相当于其他表的外键,这些表称为维度表。
由于事实表可以被看做是事件的展现,因此维度表可以被看做是事件发生的who, what,where, when, how。
星形模型名称的来源是:把事实表放在中间,维度表放在事实表的周围,它们之间的关系用线条来表示时,看起来就像是一颗星星一样。
另一种常见的模式叫做雪花模型,在雪花模型中,维度表进一步被拆解成更多的子维度表。
比如在本例中,dim_product 表中的 brand 和 category 字段可以用 brand 表和 category 表的主键来表示。
雪花模型比星形模型更加归一化,但是大家更喜欢用星形模型来实现数据仓库,因为更加简单。
在数据仓库中,表通常都是大宽表。不仅仅是事实表,维度表同样如此。
面向列的存储
在数据仓库中,事实表的存储通常是大家最为关心的,因为其数据量非常大。
虽然事实表通常都是大宽表,但是在分析查询的过程中通常只需要 4 到 5 个字段。
大多数 OLTP 数据库都是面向行存储,意味着每一行的所有数据都紧接着上一行所有数据存储,文档型数据库也一样。所以,如果事实表使用面向行存储的数据库,每行将有大量无用的数据被加载到内存。
面向列存储的原理是:将每一列的所有数据都连续得存储在一起。如果每一列的数据都单独存储在一个文件中,一次查询只用读这些想要的列文件就可以了。
列压缩
每列中有重复数据的概率非常大,因此对压缩很有利。
常用的压缩策略是:bitmap encoding(位图编码)(可以参见这篇文章)。见下图所示:

查询对应的条件时,可以对位图进行相应的 AND(位与) 或者 OR(位或) 操作。
并行向量处理
列存储中的排序
理论上来说,对列存储引擎而言,行数据根本不用排序。
然而我们仍然可以像 SSTables 一样对其进行排序操作,从而起到索引的作用。
例如,如果时间是经常被范围查询的条件,那么可以将其作为第一个排序字段,从而减小范围查询的时间,不用全列扫描了。在第一个排序字段的基础上还可以继续添加后续的排序字段。
排序后还有一个好处是:可以帮助列压缩。如果首个排序字段的唯一值不多,将为压缩带来很大的好处。
向列存储写数据
所有这些优化都是为了大量读而设计的,但所有这些优化都为写数据带来困扰。
不能考虑就地更新类型的方式,比如 B-树,因为每一次写入都会更新所有的列数据,实在太糟糕了。
而 LSM-Tree 类型的存储方式就非常适合这种列存储数据库。
聚合:数据立方和物化视图
既然大部分数据仓库处理的数据都和聚合函数计算相关,那么为什么要浪费大量的运算资源来实时计算呢?另一种思路是:将常用的聚合函数和方法应用在数据上并缓存起来供以后使用。
一种产生这些缓存数据的方法是 物化视图。
物化视图是将计算后的结果存在一张类似表的结构中,而这个表的数据是被写入硬盘中的。
由于每次数据更新都要更新这个物化视图,所以常见的 OLTP 数据库很少采用这个方式,但对于多读少写的 OLAP 数据库,这很合适。
一种常见的物化视图是数据立方。这是一个根据不同维度聚合而成的网表。
下图是一个二维数据立方:

基本思路如上图所示。
数据立方的优势在于对一些特定的聚合查询,速度非常快,因为已经提前计算好了。
劣势在于:不够灵活。
所以大部分数据库都尽量保存所有的原始数据,但对一些常见的聚合数据使用 数据立方 来提速。
第三章就此结束了。