CMU15-445 数据库系统 Midterm 总结

Relational model

  • 主要是 Integrity constraints 和 relation algebra。
  • 这个在数据库课也学了,就不重复了,基本就是那几个符号而已。

SQL

  • 基本的SQL 操作,Where 谓语, 输出控制 limit order by 这些也不重复了。
  • 主要记住先 join 再查询会快很多。而不是求笛卡尔积。
  • 445课程主要还学一个 CTE 的用法,有 CTE 的好处是可以写递归查询进行某些拼接,但是也不太好用。最主要可能是说避免看到太长的嵌套而导致问题。OLAT 用多一点。
  • 窗口 PARTITION BY 也要掌握,主要是 aggregate over xx partition by

Storage

  • 首先是几个 policies 的优缺点和选择要记住。LRU 需要用双向链表和 map 实现。
  • LRU 只是最近的时间并不是 FIFO(有问题对于一个进程频繁 miss reload evict),clock 算法是一个时间窗口内的 LRU,也不用复杂的数据结构,cursor。
  • fix length 和 var length 的数据区别。转移字符。bitmap。
  • file 的存储,一个  heap file,一个 seq,heap 基本就是一个链表,我也不知道他两个分开列什么意思。
  • 对于 var length,我们也用 slot 来存,基本方法是一个 header,然后头部一堆 slot array 存储 offset。双指针到中点直到用完一个 page。
  • page 的概念和 buffer pool。我们永远比 OS 知道地更多,所以不要用 OS。
  • LOG 系统,好处和坏处,好处是很容易重建,以及总是保证 seq 读写。(level db),可以结合 index 用。
  • 不到逼不得已不要用 numeric since 他的运算不是 CPU 运行的。
  • blob 可以用外部文件,但是不要这样用 数据库。
  • cloumn base 和 row base 存储,记得分别的 pro 和 cons。主要是 OLAP 和 OLTP 的区别。原因是 cache 和 io。
  • HTAP 是一战全链路打通,有空看一下 tidb 的论文。

HASHING

  • benchmark 的spike 原因:对齐的时候更容易 cache conflict。最好用的是 xxhash3.
  • 静态哈希,线性探测退化 On 才能判断不存在。
  • robin  hood 基本就是劫富济贫,要记录冲突的次数。空间换时间,实际性能不好。
  • cuckoo 就是 bucket 或者 double buffer(google hashing),两个 hash 函数随机选或者看有没有冲突。位置有人了就踢他出来。查询总是 O1,插入最坏无穷此时进行扩容。
  • 动态哈希
  • extendible hashing,通过 radix 树或者哈夫曼前缀码差不多的东西控制哪些前缀用哪些 bucket
  • linear hashing (用来 partition 的)涉及桶的分裂摊还代价,实际 partition 就用这个。用 cursor 来 track split 是为了保证 fine grained 的 lock。不管哪个 bucket overflow,都只 split split pointer 的地方。区分是原来的位置还是新位置(bucket)是用老 hash functin hash 之后的值是在 split point 上面还是下面,如果在下面,就不用 probe 第二个函数了。但是这个的 8 就算 mod 第二个函数也在 0 即上面(类似 java 的2倍扩展)

RWLOCK实现

  • 关键一是 spinlock(mutex) 用来保护 meta(count 之类的)
  • 然后 wait lock 睡觉前会释放 mutex,醒来重新获取 mutex。
  • 读者锁睡觉的情况是写者排队或者读者最大。
  • 写者所睡觉的情况是已经有写者排队了,不然他就排队,然后睡觉等最后读者释放。

Tree Index

  • B+树的所有要点。
  • value 可以是 tuple 或者 record id,如果 tuple 很小,可以直接用 b+树做存储。(clustering index)。如果常用一些 col,可以 b+ 树存部分 col(partial index)(create index on foo(a, b)),如果查结果是 a b 直接返回(covering index)。
  • key 不一定要 unique 因为可以通过 append tuple id 实现。
  • key 可以是 derived 的,不一定就是 schema 里面。
  • varchar key 实现方式,最简单是fix length KV pair 存储,节约空间和二分法都要用 slotted page 方案。
  • clusterd index 和 多索引,多关键字查询怎么用单个索引加速。bitmap 记录 record id 然后排序使用 sequential scan。
  • 和 b 树区别
    • 可以 bulk insert 自底向上建树 while B 树要再中间节点存数据。
    • 支持 range query,对于 like% 的索引等。
    • 稳定性好,查询高度保证一致,根据局部性一般只有底部的节点会经常 evict & reload,路径上很多重合,不用存最终的 record id 而是 page id 可能也更节约从而更加矮。
  • 二分查找智能用于非 var char 除非添加一些冗余信息或者拆分(fix length Prefix)。
  • one time optimization 和 durable optimization,后者可能进行 clustering。
  • latch crabbing 和 coupling 接力耦合
  • 安全 node 和不安全 node,安全 node 不需要祖先的锁。(stack)
  • latch 的优化方案,optimistic 和 pessimistic。restart 方案。
  • 先 opt 再 pess
  • 死锁一定要按顺序,不然就 kill 然后 restart。死锁四个必要条件:mutal exclusion,hold and wait,no preemption, circular wait。
  • livelock,两个都是 restart 情况很少。
  • radix 树做 full text search index,主要是二叉树(0 1)然后多位改进(01 10 00 11 四叉树),对于重复 bit 串进行路径压缩。
  • radix 树用于内存管理,用 id 查找指针(倒排索引),以 buffer 为例,OS 的文件一般很大,但是 cache 可能只 cache 到某个 page,需要根据文件 offset 来倒排索引到 page id。mmap 也可以这样,通过访问的 offset 决定要 lazy load 哪一块 page 进来,而不是整个文件。(mmap 每个 address space 都有一个 radix 树)。

Sorting

  • 两路 merge sort 很慢,不能利用所有的 page。可以 double buffering 和 prefetch,io parallelism。
  • 多路 merge sort 要进行很多次,然后进入到下一个重复的 多路 merge sort。
  • merge sort 只是用在 page 之间的,内部还是要么用 quicksort。如果需要稳定排序,内部也用 merge。堆排序用于 limit N 即 top k in order 问题。
  • 为什么 stl sort 不会退化:因为快排退化的原因是倒序的时候要反过来,而完全有序也会必须 nlogn 因为 pivot 选择的问题。如果用了 median,最好情况是都要递归 nlogn 次,无法优化。堆排非叶子节点建堆要时间,然后每次取 root 和末尾叶子换,重新整堆得到新的顶,所以是 3n/2. 插入排序数据量少的时候流水线很快,数据量大的时候递归很深,减少空间掉到 nlogn 所以改用堆排空间 O1 . 总之堆排是避免空间太大,插入是用内存读写避免分支(少量数据用寄存器重命名就行了)。快排减少分支的方法是避免边界判断,需要做 dummy。面试还是用老办法。插入比选择快是因为利用了局部有序性导致平均比较次数可能更少。
  • 代价评估我不复习了,暂时没用。

Aggregation

  • 首先一种方法是维护一个 zone map,直接返回数据。zone map 的算法实现无非就那些,什么最大最小栈(如果有 cluster b+ tree index 更方便),主要是增量算法的量更容易保留。
  • 对于 group by,用hashing 做 aggregation,基本方案是用 hash 决定放到哪个 bucket(partition),这样保证了 partition 里面的基本都是同一个 key 的。
  • 然后再 in memory hash table 对每个分区进行 rehash,hash 到同一个位置就进行计算 aggregation,这是为了生成最终的每个 group 的 unique 结果。
  • 过程也可以 bypass buffer pool 因为可能都是些临时数据。

Join

  • 先 project 还是先 join 会影响 io 和数据传送性能。query optimization。
  • nested-loop 总是最bottom的方案,比如所有 key 都一样,必须笛卡尔积,最终 fall back 成这个。但是这个不能最最普通的方案,因为 cache missed reload 浪费,一个是多 page 内切换,一个是 match 的另一个关系像 csapp 说的切换。
  • nested-loop-variants 第一种是 block nested loop,我们先笛卡尔积所有的 page pair(至少能至少保证内循环的 page 不会 evict 和 reload),再 nested loop。实际不只两个 buffer 的时候加速,如果某个关系能 fit in memory 就是线性的,能在百毫秒内完成。
  • 用 index 来 join 很快。但是 on the fly 很慢,要看 trade off,以及是 one time 还是 durable 的优化。
  • sort merge 也能用,但是涉及backtrack 退化 N。cluster index 利用时加速。如果有 cluster index 就用 sort merge
  • hash join 的方法是一个关系 hash 到 buckets 里然后另一个线性 probe 生成结果。如果是 col base 就 hash 过程存整个 tuple,防止更多 io,row base 就存 identifier 就行了。
  • build 过程创作一个 bloom filter,这样 prob 的时候不在 filter 的第二个关系就不用 hash 了(因为hash table 是涉及 page 的,而且你不进去看也不知道有没有)。
  • 因为 hashtable 不 fit-in 就很多 evict(每 probe 一个就要 evict), grace hash join 是用 nested + hash,hash 只用来 partition,对于两个 fit in memory 的 partition 就用 nested loop 来 match 。保证每个 page 只 load 和 evict 一次不会有 evict & reload 的浪费。但是常数更多 3M+3N. 递归 hash 最差情况很差。(这里 grace hash 的 hash 函数肯定是某种冲突大的)

Query Execution

  • iteratior model 适合流水线,通过独立的 thread 来运行这些内容。涉及 coordinate 等情况。有点麻烦。但是省空间。materialization model 则是 batch processing,适合 OLTP 少量查询快速不用 inter function communate(各种函数调用等于一个生产者消费者问题)批处理不用。但是如果 IO 量大了还是要 fall back 到 iterator model。迭代器支持 limit 不用访问全部。
  • double buffer 技术,由于巨量 itemediate 结果  data copy 和 transmitting 会浪费 buffer pool 和引发 io瓶颈,多线程 IO 。或者 buffer pool bypass。
  • vectorlized model 基本就是段页式的 compromise 而已。让函数做更多事情,利用上 Cache。所有的 OLAT 都用这个方法。对于一些操作,也可以利用 CPU SIMD。
  • 需要编写 DP 版的 bottom up 的 pipeline 而不是使用递归函数调用。自从递归调用会频繁引发 evict 和 reload。
  • 流水线 fallback 的情况是等待,pipeline breaker 必须 block。所有的 aggregate 和 sort 都是 breaker,join 也是。
  • 必须 sequential scan 的情况,比如没有 index 进行 range query,或者有 index 也 range query。
  • zone map 记录 aggregate function,有了 min max 可以快速排除 out of range query。但是 zone map 只利好 OLAT 对 OLTP 来说很难维护,比如最大最小栈必须消耗很大的空间。(side-info)
  • Late materilization 优化,就是 materialization 的时候只记录 tuple record id,然后 bitmap。对于一些操作很有用,比如 where 多个 clause ,and 或者 or 直接多线程 run inter query 的 intra operator 之后对 bitmap 操作即可。
  • index scan 如何选择 index,对于大量可能 99% 都符合某个条件,index fall back 为 seq scan。即区分 selective scenario 和 index 不是很 selective 的情况。
  • multiple-index 的使用,还是 bitmap。
  • 对于 index 不是 clustered 的,还要写磁盘调度器,对于收集到的 record id,我们 bitmap 之后 sort ,或者直接 bitmap 就支持分区 scan 了。
  • 默认使用一个隐含的自增id做 cluster index。最好还是指定常用的 primary key。
  • 解析语法树,对每个 tuple 运行表达式树 is super slow。有 sql prepared statement 一次编译多次运行,可以 JIT。当然还有 const optimization。(mysql 现在版本没有 JIT)

Parallelism

  • 得益于 dbms 的 logical layer 和 physical 是独立的。
  • 能够提高 throughput 和 latency 性能。
  • 利用 CPU SIMD,还有 GPU 提供更好的并行(并没有)。
  • 商业决策 TCO total cost of ownership,买车并不止一个买车钱属于。
  • cpu bound 问题做 computing parallelize,IO bound 做 IO parallelism。
  • parallelism vs distributed,一个是很多 local CPU 资源,reliable 的 IPC。一个是很多远程的慢速不可靠 IPC,尽量减少 IPC。CAP consistency, avaliablity, partition tolerance.
  • DBMS 对 queries  的 process model 分为 intra 和 inter,然后 inter 也分为 inter operator 和 intra operator。inter 的 coordinate 问题很多,涉及 transaction ?很麻烦。Lec 16 才讲这个。知道 inter 提高 throughput,intra 提高 long query 的 latency 性能就行了。
  • postgres 输了因为他用了 process 模型,but when we view back to the late 1990s,POSIX 都没有,也没有 pthread。虽然 thread 模型 fail 全部就 down 了,但是并不影响主流的新 dbms 哦都用 thread model。Linux 的 thread 还能控制哪个 core,实际控制度很大。
  • 用 dispatcher 来分发,为了 optimal 利用 cores,我们不能总是 fork (或者 create thread)而是采用一个 worker pool 控制有限的独立 worker。
  • pipeline 和 producer、consumer problem。
  • sqlserver 的 exchange operator 概念,他基本是一个管理所有 sub query(intra operator),他做三件事,要么 garther 然后传到上一层要么继续 repartition (recursion 的)比如上层可能做 group by,他这里 group 一下继续分发(distribute)了。
  • inter operator 就是 pipeline 了,我们要保证 pipeline 饱和才行,需要 coordinate。
  • bushy 是很多的 inter 然后交叉 exchange ,这个有点看不懂。
  • IO 可以用 raid 冗余独立(廉价)磁盘阵列,这个在 install 的时候 user define 也行。
  • 通过 symlink 实现不同硬盘(实际就是快捷方式),又要用到 OS 的 IO 的,不过直接 no buffer 用 O_DIRECT 就行了。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值