摘要:本文从读取和写入的角度分别描述了行存和列存的IO模型,并对文件结构做了简单介绍。

本文分享自华为云社区《GaussDB(DWS)基本IO框架》,作者: Naibaoofficial。

行存IO管理框架

存储结构

  • OID(Object identifiers):对象的唯一标识。
  • 每个表存在对应数据库的文件夹中,用relfilenode标识。

例如表row1,可以直接查询对应的文件

test=# select pg_relation_filepath('row1');
pg_relation_filepath
----------------------
base/16385/55984
(1 row)
  • 每个表的读取写入以页(文件块)为基本单位,页的大小是一个BLCKSZ,默认8KB,其结构如下:

  • Tuple保存了当前一行的数据,分为Header和Data两块,头部保存元组的相关信息(列数,事务信息,是否有Toast表等)。
  • 每个Tuple最大为2kb,若Data过大无法压缩至2KB,则采用额外的Toast表存储,此时Tuple内的Data保存Toast表的相关信息。

GaussDB 行存框架:

这里面涉及到几个比较大的内核机制:

  • 本地缓存:

这里面的本地缓存介绍了三个比较常用的缓存结构,这里直接引用了官方的英文解释。

temp_buffers: Sets the maximum number of temporary buffers used by each database session. These are session-local buffers used only for access to temporary tables.

work_mem: Specifies the amount of memory to be used by internal sort operations and hash tables before writing to temporary disk files.

maintenance_work_mem: Specifies the maximum amount of memory to be used by maintenance operations, such as VACUUM, CREATE INDEX, and ALTER TABLE ADD FOREIGN KEY.

  • 共享内存:可由整个Gaussdb共享

包括shared_buffer和wal_buffer, 分别用来存放Page和Clog,Wal Segment。

  • WalWriter,BgWriter:

主要是将共享内存的内容落盘,WalWriter一般是在事务提交时就需要落盘,但是有时候可以放弃一定的事务一致性原则,从而让WalWriter异步落盘加快速度。BgWriter负责将shared_buffer中的内容落盘。

  • 外存管理:

负责上层与外存之间的文件交互。

IO管理框架:读取

读取的过程相对简单,就是从物理文件先装到shared_buffer中,然后从shared_buffers返回相关的结果。

shared_buffers中就是以Page为单位进行存储的,因为每个Page的大小是固定的,所以shared_buffers能存放的page个数也就是确定的。这里面就需要考虑一个问题,因为这个资源是共享的,如果一个线程读取了大量的文件,这样势必会使得其他线程的缓存命中率下降。

GaussDB在这里引入了Ringbuffer的机制,可以限制一个线程所使用的shared_buffers的大小,从而解决掉这个问题。

IO管理框架:写入

  • 写入操作是增加的新的元组,Update操作相当于先Delete,再Insert。
  • INSERT

  • UPDATE

将旧元组标记为Dead,然后插入新的元组,由Vacuum负责清理。当然,这里面Data变为DELETE只是用来描述删除的是此Tuple,实际上Data当中的值是不变的。

  • 写入的整体逻辑:

GaussDB行存在写入时,将元组信息先写入到shared_buffers,然后用bgwriter刷入磁盘,这样在事务提交时就可以避免磁盘的IO开销,提升性能,为了保证一致性和恢复,使用wal日志和checkpoints可以实现日志先落盘(也可以异步)和redo等操作。

列存的IO管理框架

列存的存储单元

  • 列存的存储单元为CU(CStore Unit)
  • CU的大小为8k对齐
  • 适合大批量导入的场景
  • 同一列的CU存在一个新文件中,大于1GB时,切换到新文件中。
  • 列存用一个CUDesc的行存表描述CU的相关信息,可以理解成为一个Toast表。
  • CUDesc:行存表,记录CU的相关信息, 主要属性如下:
  1. col_id,cu_id: 第col_id列,第cu_id个CU
  2. min, max, row_count, size
  3. cu_mode: information mask(RLE,LZ4,Delta表等)
  4. cu_pointer:指向每一个CU,记录delete bitmap
  5. magic:和CU头部的magic相同,校验使用

CU结构

列存索引

这里介绍两个索引,C-Btree和Psort,这里不做过多介绍。
主要涉及的是IO相关的内容。

C-Btree

  • 索引结构和行存无差别,同样以行存形式存储
  • C-Btree可以提升点查效率
  • 存储key->ctid(cu_id, offset)
  • 过程:
  1. 根据B-tree索引找到ctid集合
  2. 对集合进行批量排序(减少IO开销)
  3. 在CUDesc找到对应的cu_id,根据offset找到数据
  • 举例,等值查询 n=49, 范围查询 23<n<64。

PSort

PSort是一个聚簇索引,对索引进行排序,然后将排序后的索引和行号存入一个新的表,用单独的列存表存储。
简单示意如下,图片来源:https://www.modb.pro/db/108155

IO管理框架:读取

  • 读取过程:
  1. 根据where条件,做MIN/MAX过滤的谓词条件
  2. 加载CUDesc
  3. MIN/MAX过滤
  4. 读取CU到CU Cache中
  5. 解析并填充
  • CacheMgr: 用来缓存CU到内存中,可以提高重复查询的性能。
  • CU的物理文件:
    1. CStore_1.0: 当前基本不怎么实用
    2. CStore_2.0: 重整了CU的文件结构,避免列数过多导致文件结构复杂。

IO管理框架:写入

列存的插入要分两种情况,少量的插入和大量的插入,列存主要是对大批量数据设计的,因此为了弥补小量插入的打包CU性能开销,设计了一个delta行存表,用来记录插入结果,可以减少膨胀和提升性能,最后定期的整理。

  • 写入框架如下

列存的删除比较简单,如果是delta表,先从delta表中删除满足谓词条件的记录,然后在CUDesc表中更新待删除CU的delete_bitmap。

点击关注,第一时间了解华为云新鲜技术~

从读写角度,带你了解数仓的IO基本框架的更多相关文章

  1. 对象流,它们是一对高级流,负责即将java对象与字节之间在读写的过程中进行转换。 * java.io.ObjectOutputStream * java.io.ObjectInputStream

    package seday06; import java.io.Serializable;import java.util.Arrays; /** * @author xingsir * 使用当前类来 ...

  2. 带你封装自己的MVP+Retrofit+RxJava2框架(一)

    前言 文本已经收录到我的Github个人博客,欢迎大佬们光临寒舍:我的GIthub博客 看完本篇文章的,可以看下带你封装自己的MVP+Retrofit+RxJava2框架(二),里面封装得到了改进 本 ...

  3. 从数据的角度带你深入了解IPFS

    IPFS 和区块链有着非常紧密的联系, 随着区块链的不断发展,对数据的存储需求也越来越高.本文从IPFS 的底层设计出发, 结合源代码, 分析了IPFS 的一些技术细节. 一.概述 IPFS 和区块链 ...

  4. 小数组的读写和带Buffer的读写哪个快

    定义小数组如果是8192个字节大小和Buffered比较的话 定义小数组会略胜一筹,因为读和写操作的是同一个数组 而Buffered操作的是两个数组

  5. 吉特仓库管理系统-ORM框架的使用

    最近在园子里面连续看到几篇关于ORM的文章,其中有两个印象比较深刻<<SqliteSugar>>,另外一篇文章是<<我的开发框架之ORM框架>>, 第一 ...

  6. 从IT的角度思考BIM(二):模式与框架

    我们满怀着美好期许,鼓起勇气敲响了 BIM 世界的大门.忽然人群中有人高呼:BIM 已死,大家都散了吧! 这时人群开始骚动起来.“我早就说这玩意是忽悠人的吧,你们不信还偏要来”,“我花了好多钱准备这次 ...

  7. 带标准IO带缓存区和非标准IO 遇到fork是的情况分析

    废话不多说 直接代码 #include<stdio.h> #include<sys/types.h> #include<unistd.h> #include< ...

  8. 带你一文搞定 IO 流相关核心问题

    问:简单谈谈 Java IO 流各实现类的特性? 答:java.io 包下面的流基本都是装饰器模式的实现,提供了各种类型流操作的便携性,常见的流分类如下. 以二进制字节方式读写的流: InputStr ...

  9. 文件读写(一)利用File静态类 System.IO.FileInfo、DirectoryInfo、DriveInfo

    提供用于创建.复制.删除.移动和打开单一文件的静态方法,并协助创建 FileStream 对象. 一.读文件: 1.返回字符串:File.ReadAllText() string readText = ...

随机推荐

  1. Swift 介绍

    简介 Swift 语言由苹果公司在 2014 年推出,用来撰写 OS X 和 iOS 应用程序 2014 年,在 Apple WWDC 发布 几家欢喜,几家愁 愁者:只学Object-C的人 欢喜者: ...

  2. UDP数据包最大传输长度

    概念以太网(Ethernet)数据帧的长度必须在46-1500字节之间,这是由以太网的物理特性决定的.这个1500字节被称为链路层的MTU(最大传输单元). 但这并不是指链路层的长度被限制在1500字 ...

  3. iOS 如何监听用户在手机设置里改变了系统的时间?

    如何监听用户未退出APP但通过Home键在手机设置里改变了系统的时间? 用户虽未退出APP,但是当它按Home键退到后台时 ,会调用该方法: - (void)applicationDidEnterBa ...

  4. 如何综合运用对称加密技术、非对称加密技术(公钥密码体制)和Hash函数 保证信息的保密性、完整性、可用性和不可否认性?

    一.几个问题 在提出问题之前,先创建一个使用场景,发送方(甲方)要给接收方(乙方)发送投标书.大家知道,投标书都包括发送方的标的,这个标的是不能被竞标者知晓,更不能被竞标者修改的.在传输的投标书时,提 ...

  5. 基于PXIe接口的CoaXpress高速相机图像采集、回放

    PXIe简介 PCI eXtensions for Instrumentation or PXI is a computer-based hardware and software platform ...

  6. ASP.NET Core 6框架揭秘实例演示[04]:自定义依赖注入框架

    ASP.NET Core框架建立在一个依赖注入框架之上,已注入的方式消费服务已经成为了ASP.NET Core基本的编程模式.为了使读者能够更好地理解原生的注入框架框架,我按照类似的设计创建了一个简易 ...

  7. Jetpack的ViewModel与LiveData

    本文基于SDK 29 一.ViewModel与LiveData的作用: 1.viewModel: 数据共享,屏幕旋转不丢失数据,并且在Activity与Fragment之间共享数据. 2.LiveDa ...

  8. Solution -「多校联训」数学考试

    \(\mathcal{Description}\)   Link.   给定 \(n\) 个函数,第 \(i\) 个有 \(f_i(x)=a_ix^3+b_ix^2+cx_i+d~(x\in[l_i, ...

  9. ASP.NET Core 6框架揭秘实例演示[07]:文件系统

    ASP.NET Core应用具有很多读取文件的场景,如读取配置文件.静态Web资源文件(如CSS.JavaScript和图片文件等).MVC应用的视图文件,以及直接编译到程序集中的内嵌资源文件.这些文 ...

  10. CentOS7更新OpenSSH8

    今天使用漏洞扫描工具扫描了一下系统漏洞,发现有一个openssh版本的漏洞.所以本着安全的原则修复一下. 第一时间打开百度搜索相关内容,大多数是编译安装的.每个人的环境和版本也不一样.有一定连不上去的 ...