数据库工作负载#
OLTP#
OLTP:联机事务处理
每次快速地对一个小范围的数据进行读取、更新的操作。
OLAP#
OLAP:联机分析处理
OLAP 用于支持复杂的分析操作,提供决策支持等。
HTAP#
混合事务 + 分析处理
一种新的工作负载,将 OLTP 和 OLAP 结合起来。
存储模型#
N-Ary 存储模型(NSM)#
在 n-ary 存储模型中,DBMS 将包含所有属性的元组连续存储在单个页面中。
对于 OLTP 来说,这是非常理想的。
优点:
- 插入、更新、删除非常快
- 对于需要整个元组的查询非常友好
缺点:
- 对于需要扫描整个表或只需要一个属性的查询非常不友好
分解存储模型(DSM)#
将每个元组中的每个属性单独分开存储。
也可以称为 “列存储”。
对于只读的 OLAP 操作非常友好,尤其是那些只需要扫描部分属性的操作。
优点:
- 减少 I/O 浪费
- 更好地进行查询和数据压缩
缺点:
- 对于单点修改查询更新等操作较慢。
为了实现这种操作,通常有两种方法:
- 为每个属性设置固定的字长,这样我们只需要得到偏移量就可以准确地查找到我们所需的数据。
- 一个更罕见的操作是,使用一个形如
(id:pos)
的元组来存储值,表示第 id 的值存储在 pos 位置上。
数据库压缩#
I/O 是非常耗时的,通常是整个数据库的瓶颈,因此 DBMS 广泛使用压缩算法来提高性能。
通常我们需要在速度和压缩率之间进行权衡。
压缩粒度#
- 块级别
- 元组级别(仅适用于 NSM)
- 属性级别
- 列级别
Naive 压缩#
使用 “通用” 压缩算法通常也是一种解决方案。但是一旦使用这种方法,DBMS 就不知道我们操作的数据是什么,直到解压缩完成。
提供的输入:
→ LZO(1996 年)、LZ4(2011 年)、Snappy(2011 年)、Oracle OZIP(2014 年)、Zstd(2015 年)
为了提高速度,我们需要另一种压缩方法,即使在压缩后,我们也有办法获取其中的信息来加速。
列压缩#
运行长度编码(RLE)#
可以将一些连续出现在同一列上的值压缩成一个形如(value:pos:num)
的三元组。
其中:
value
表示值pos
表示该值的起始位置num
表示该值重复的次数
但是该方法可能存在一些缺陷
转换后
位填充编码#
一些数据对我们来说是非常冗余的,我们可以通过位填充的方式来减少这些冗余。
将int64
转换为int8
大大减少了所需的空间。
但是该方法存在一些缺陷,可能会存在部分信息不符合int8
的情况。
因此,我们需要以如下方式进行存储。
但是该方法只能在额外存储信息较少的情况下使用。
位图编码#
当每个属性的值较少时,我们可以使用位图的方式进行存储。
例如,当只存在F
和M
两种值时,我们可以用01
表示是或否。
Delta 编码#
在许多情况下,例如室温,我们的统计结果可能存在在一定范围内的密集值。
因此,我们可以通过确定一个值后,后续的所有值都可以通过delta
的形式存储。
增量编码#
我们通常也可以通过取前缀 / 后缀的形式得到最终结果。
字典编码#
当一张表中可能存在多个值,并且这些值存在于不同的位置时,我们可以通过字典的形式得到这些值所在的位置。
这也是最常用的压缩方法。