cmu 15-445 2022 fall 课程笔记:《05 columnar databases & compression》

156 阅读6分钟
仅做个人笔记 
中文和英文的课都会看,中文看的是Moody老师的21年fall,英文是油管上的官方视频22年fall

英文课开头

英文2022年的课程第五节开头讲的和2021年课的第四节课后半程一样:OLTP和OLAP的介绍(事务型和分析型)以及混合型Hybrid

N-ary storage model(NSM)行存数据库

优点:非常适合更新和插入

缺点:当只需要一部分数据(部分列),但仍需要读取所有行,有IO的浪费

列存储或者分解存储 Decomposition storage model(DSM) 优点:减少了IO,只需取出SQL指定的列的页就可以了。 缺点:对于插入删除更新的操作比较耗时,如果数据预先排好序了,那会更慢。

后续看课会以中文课为主了,英文课看起来太累了

buffer pools简介

buffer Pools:指的是内存池,从内存中开辟一片区域作为缓存,存储数据库的页。

用户修改和插入新数据时,先存放在内存缓存中,等commit之后(存疑),再写回磁盘

缓存池有两个控制:空间控制,时间控制

空间:目标是把用户常用页在磁盘中集中起来,可以存放到缓存池中

时间:什么时候把磁盘上页读入内存中,或用户新写入的页存入磁盘;要最大限度减少存取磁盘的时间,减少用户等待磁盘IO的时间

面向磁盘的DBMS

读取流程:执行器通知内存要读取哪一个页(page #2),内存池没有该页,需要从磁盘中读取目录页,找到对应页的位置,从该位置处读取执行器所需页,然后读到缓存池中,将该页再传输给执行器。

image.png

三个问题:缓冲池管理、替换策略、其他内存池

Buffer Pool Manager

磁盘文件以页分开,内存中也是按页分开,但内存中一般以帧为名,即frame,一般一个frame可以缓存一个磁盘的页,frame与page对应

内存池一般有几个G大小。

可以使用page table 来索引内存池,可以打图钉和加锁

locks vs latches

locks:一般指逻辑上的,锁某个表。high level

latches:实际上的锁,对每个表的页进行加锁,实际加锁。

page table vs page directory

page table 是内存池中的frame的索引

page directory 是磁盘上存储所有页地址的页

allocation policies

从磁盘中缓存来的也放在哪里。

全局策略:统一安排所有事务所需的所有页来缓存在哪,统一安排。

本地策略:为每一个事务缓存的页有单独的策略。

buffer pool optimizations

用于提高缓存池性能的策略

multiple buffer pools

多缓存池

文件的页是不一样的,索引,数据,元数据。

存索引、数据、元数据都有专门的内存池

每个database 都有一个buffer pool

每种页类型,使用一个buffer pool

对此,有以下方法实现:Object ID 和 hashing。 对数据查看他的Object ID,按此分配缓存池。将数据进行hash,分配缓冲池。

image.png

预读取

pre-fetching

全表扫描: 读 0 1 2 3 4 页

读0和1时,预读取2,替换0号,依次类推

image.png

索引扫描: buffer pool 读取顺序:根,判断走左还是右子树

image.png

scan sharing

同步扫描。两个SQL被发现是扫描的是一件事,两个SQL会同步执行扫描。

image.png 后续,未处理完的SQL,再继续处理剩余的扫描。

但是有问题:如果Q2有limit的限制,会输出错误。

bypass (旁路)

不进内存池的情况

执行所有数据都是从磁盘到内存池,再到执行器。对于某些表,只是用一次,用于缓存有些浪费。优化方法:使用另一个区域来存储这种数据。

优点:不缓存就没有淘汰的工作。算子如果需要读取大片数据时,可能就是扫描一次,就不再使用,所以不进内存池更好。sorting和joins的中间结果,是不会进内存池的,直接放回。

操作系统对于页的缓存,对于这种的缓存是不会进入内存池的

问题:冗余、淘汰策略较差、无法直接优化磁盘IO

缓存替换策略

缓存池满的时候,将新数据如何提空。数据库需要清空一些帧,并将新页存入缓存

要求:正确的、准确的、快、元数据更新开销小

LRU(最近最少使用)

策略:记录读入缓存池的时间戳,替换近期最久没有使用的页。

CLOCK:模糊的LRU。环形数据结构,对每页设置标志位ref,该页被读取时,设ref是1。让时针顺时旋转,当ref=1时,清0,但不驱逐,继续旋转,如果指到ref=0,说明,指针旋转一圈也没被使用的页,所以就驱逐该页。

LRU的问题:对于全表顺序读性能很差。因为要把表所有页都读取,这种情况下,其实新读取的页,在用完之后也没用了。sequential flooding。 也即,只是把时间上最长未使用的页替换掉,但是实际上,可能由于缓存池比较小,导致容易满了,虽然换了时间上最长没使用,但是,恰好下一次使用的就是该页,甚至,该页属于被经常访问的页,那么这种情况LRU是有问题的。

LRU改进:

LRU-K 查看页是否是周期性读。

按事务和语句进行驱逐 把单独本地事务有关的页进行驱逐

priority hints 优先级提示,执行器给缓存池指示,某页比较重要,不能轻易清理。例如:索引树的节点,hint提示根节点很重要,不要在缓存池中轻易清理。几乎所有数据库,一开机,索引树的根节点就会缓存到缓存池中,并且不清理。

dirty pages

脏页:内存中的页内容和磁盘中的页内容不一致

如何把内存的变换写回磁盘。

fast: 如果数据库清理内存时,发现该页没脏,则按规则淘汰。

slow:数据库发现,读入内存的页被修改了,数据库不能直接清理该页了,需要将该页内容写回磁盘,再清理。

如果发现短时间不使用,可写回再清理,如果短时间再使用,则先不写回,维持在内存中。

问题:修改完,但是没存入磁盘中,此时断电的话怎么解决? 解决:日志

刷脏:将修改过的内存池中的数据,写入磁盘中。可以选择集中将脏页输入磁盘;如果脏页已经写回磁盘了,则该页可以被清理;日志与脏页之间的关系要好好处理,脏页未持久化(存磁盘),则日志得持久化,两者至少有一个持久化了。

缓存别的东西

例如:sorting join buffers, query caches(一模一样的SQL语句,结果缓存),maintenance buffers,log buffers,dictionary caches

总结

DBMS自己处理缓存会比OS要好

优化缓存:利用查询计划优化:

驱逐

分配

预取

image.png