admin 管理员组文章数量: 1086019
行式存储和列式存储的数据库
定义
关系数据库采用的数据存储有两种方式:行式存储和列式存储(也被称为columnar或C-store)
行式存储
是按记录组织数据的数据库,将与记录相关联的所有数据彼此相邻地保存在内存中。面向行的数据库是组织数据的传统方式,为快速存储数据提供了一些关键优势。它们针对有效地读取和写入行进行了优化。因此又相比列式存储的数据称为写优化的数据库。
常见行式存储的数据库:Postgres、MySQL
列式存储
是按字段组织数据的数据库,将与字段相关联的所有数据彼此相邻地保存在内存中。列式数据库越来越受欢迎,并为查询数据提供了性能优势。它们针对有效地读取和计算列进行了优化。因此相比行式存储被称为读优化的数据库。
常见的列式存储的数据库:Redshift、BigQuery、Snowflake
市面上也有少许数据库既支持行式存储也支持列式存储的,例如:SAP HANA
行式存储的数据库
传统的数据库管理系统通过这种方式存储数据。它们主要以读取和写入单行数据为主要功能导向,这也决定了采用行存储架构。
在行式存储的数据库中,数据是逐行存储的,这样后一行的第一列将紧挨前一行的最后一列。
例如,让我们以Friends数据为例:
Name | City | Age |
---|---|---|
Matt | Log | 27 |
Dave | San | 30 |
Tim | Oak | 33 |
这些数据将按行存储在行式数据库中的磁盘上,如下所示:
Matt | Log | 27 | Dave | San | 30 | Tim | Oak | 33 |
---|
这允许数据库快速写入一行,因为只需要将新一行的记录直接添加到数据的末尾。
行式数据库的写入
例如原有的数据为:
Matt | Log | 27 | Dave | San | 30 | Tim | Oak | 33 |
---|
如果我们要新增一条新纪录
Jen | Van | 30 |
---|
我们可以将它附加到当前数据的末尾:
Matt | Log | 27 | Dave | San | 30 | Tim | Oak | 33 | Jen | Van | 30 |
---|
行式数据库通常用于在线事务处理(OLTP)风格的应用程序,因为它们可以很好的进行数据库的写入。但是,数据库的另一个主要用途是分析其中的数据。这些在线分析处理(OLAP)用例需要一个能够支持数据的即席查询的数据库,在这个场景中,行式数据库比较慢。
行式数据库的读取
面向行的数据库在检索一行或一组行时速度很快,但是在执行聚合时,它会将额外的数据(列)带入内存,这比仅选择要执行聚合的列要慢。此外,面向行的数据库可能需要访问的磁盘数量通常更大。
额外数据进入内存
假设我们想从Friends数据中获取年龄总和。为此,我们需要将所有九个数据块加载到内存中,然后提取相关数据进行聚合。
Matt | Log | 27 | Dave | San | 30 | Tim | Oak | 33 |
---|
这浪费了很多的计算时间。
访问的磁盘数量
让我们假设一个磁盘只能容纳足够的数据字节,以便在每个磁盘上存储三列。在面向行的数据库中,上表将存储为:
DISK1:
Name | City | Age |
---|---|---|
Matt | Log | 27 |
DISK2:
Name | City | Age |
---|---|---|
Dave | San | 30 |
DISK3:
Name | City | Age |
---|---|---|
Tim | Oak | 33 |
为了得到所有人年龄的总和,计算机需要查看所有三个磁盘以及每个磁盘中的所有三列才能进行此查询。
因此我们可以看到,虽然向面向行的数据库中添加数据既快速又简单,但从中获取数据可能需要使用额外的内存和访问多个磁盘。
列式存储的数据库
为了对大量数据进行分析,因此有了数据仓库。这类型的数据库是针对读取进行优化的。在列式存储的数据库中,数据的存储方式是使列的前一行与同一列中的后一行相邻。让我们再次查看相同的数据集,看看它如何存储在面向列的数据库中。
Name | City | Age |
---|---|---|
Matt | Log | 27 |
Dave | San | 30 |
Tim | Oak | 33 |
这些数据将按列存储在列式数据库中的磁盘上,如下所示:
Matt | Dave | Tim | Log | San | Oak | 27 | 30 | 33 |
---|
列式数据库的写入
如果我们要添加一条新记录:
Jen | Van | 30 |
---|
我们必须在数据中查找以将每一列插入到它应该在的位置。
Matt | Dave | Tim | Jen | Log | San | Oak | Van | 27 | 30 | 33 | 30 |
---|
如果数据存储在单个磁盘上,它将与面向行的数据库一样存在额外的内存问题,因为它需要将所有内容都放入内存。但是,当存储在单独的磁盘上时,面向列的数据库将具有显著的优势。如果我们将上面的表格放入同样受限的三列数据磁盘中,它们将像这样存储:
Name | Name | Name |
---|---|---|
Matt | Dave | Tim |
DISK2:
City | City | City |
---|---|---|
Log | San | Oak |
DISK3:
Age | Age | Age |
---|---|---|
27 | 30 | 33 |
列式数据库的读取
要获得年龄的总和,计算机只需转到一个磁盘(磁盘 3)并将其中的所有值相加。不需要拉入额外的内存,它访问的磁盘数量最少。
虽然这有点过于简化,但它说明通过按列组织数据,需要访问的磁盘数量将减少,并且必须在内存中保存的额外数据量最小化。这大大提高了计算的整体速度。
当然还有其他优化方法可以让面向列的数据库获得更高的性能。
列存储的优势
更高的数据压缩率
列式数据存储允许高效压缩。特别是如果对列进行了排序,在连续内存中会有相同值的范围,因此可以更有效地使用行程长度压缩算法等压缩方法。
列操作的更高性能
通过列式数据组织,对单个列的操作(例如搜索或聚合)可以实现为对存储在连续内存位置中的数组的循环。这样的操作具有很高的空间局部性并有效地利用了CPU缓存。
此外,高效的数据压缩不仅可以节省内存,还可以提高速度。
消除附加索引
在许多情况下,列式数据存储消除了对额外索引结构的需求,因为在列中存储数据已经像为每列拥有一个内置索引一样工作:内存中列存储的列扫描速度和压缩机制(尤其是字典压缩)已经允许以非常高的性能进行读取操作。在许多情况下,不需要额外的索引结构。消除索引可以减少内存大小,可以提高写入性能,并减少开发工作。但是,这并不意味着 SAP HANA 中根本不使用索引。主键字段总是有一个索引,如果需要,可以创建额外的索引。此外,全文索引用于支持全文搜索。
消除物化聚集体
由于其列扫描速度,列存储可以在运行中以高性能计算大量数据的聚合。在许多情况下,这消除了对物化聚合的需要。消除物化聚合有几个优点。简化数据模型和聚合逻辑,使开发和维护更加高效;它允许更高级别的并发性,因为写入操作不需要排他锁来更新聚合值;它确保聚合值始终是最新的(物化聚合有时仅在预定时间更新)。
并行化
基于列的存储还简化了使用多个处理器内核的并行执行。在列存储中,数据已经垂直分区,这意味着可以轻松并行处理不同列上的操作。
何时使用行式存储和列式存储
列式存储
- 计算通常在单个或少量列上执行。
- 根据多个列的值搜索该表。
- 该表具有大量列。
- 表行数较多,需要进行列式操作(聚合、扫描等)
- 可以实现高压缩率,因为大多数列仅包含几个不同的值(与行数相比)。
行式存储
- 应用程序一次只需要处理一条记录(单条记录的多次选择和/或更新)。
- 应用程序通常需要访问完整的记录。
- 这些列主要包含不同的值,因此压缩率会很低。
- 既不需要聚合也不需要快速搜索。
- 该表的行数很少(例如,配置表)。
这篇文档主要分析了行式存储和列式存储的优劣以及如何选择相应的存储类型。
本文标签: 行式存储和列式存储的数据库
版权声明:本文标题:行式存储和列式存储的数据库 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.roclinux.cn/b/1686559881a10306.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论