仅做个人笔记
中文和英文的课都会看,中文看的是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),内存池没有该页,需要从磁盘中读取目录页,找到对应页的位置,从该位置处读取执行器所需页,然后读到缓存池中,将该页再传输给执行器。
三个问题:缓冲池管理、替换策略、其他内存池
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,分配缓冲池。
预读取
pre-fetching
全表扫描: 读 0 1 2 3 4 页
读0和1时,预读取2,替换0号,依次类推
索引扫描: buffer pool 读取顺序:根,判断走左还是右子树
scan sharing
同步扫描。两个SQL被发现是扫描的是一件事,两个SQL会同步执行扫描。
后续,未处理完的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要好
优化缓存:利用查询计划优化:
驱逐
分配
预取